its a common (yet easily fixable) error to just forget parens at the end of getter-like methods without any arguments.
The current error message for that case asks for an anonymous function, this patch adds a note asking for either an anonymous function, or for trailing parens.
This is my first contribution! do i need to do anything else?
clean$(1)_H_$(2): \
$$(foreach crate,$$(CRATES),clean$(1)_H_$(2)-lib-$$(crate)) \
$$(foreach tool,$$(TOOLS),clean$(1)_H_$(2)-tool-$$(tool))
+ $$(Q)rm -fr $(2)/rt/libbacktrace
clean$(1)_H_$(2)-tool-%:
$$(Q)rm -f $$(HBIN$(1)_H_$(2))/$$*$$(X_$(2))
#
# DEPS_<crate>
# These lists are the dependencies of the <crate> that is to be built.
-# Rust dependencies are listed bare (i.e. std, extra, green) and native
+# Rust dependencies are listed bare (i.e. std, green) and native
# dependencies have a "native:" prefix (i.e. native:sundown). All deps
# will be built before the crate itself is built.
#
# automatically generated for all stage/host/target combinations.
################################################################################
-TARGET_CRATES := std extra green rustuv native flate arena glob term semver \
- uuid serialize sync getopts collections num test time rand
+TARGET_CRATES := std green rustuv native flate arena glob term semver \
+ uuid serialize sync getopts collections num test time rand \
+ workcache url log
HOST_CRATES := syntax rustc rustdoc fourcc hexfloat
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
TOOLS := compiletest rustdoc rustc
DEPS_std := native:rustrt native:compiler-rt native:backtrace
-DEPS_extra := std term sync serialize getopts collections time rand
DEPS_green := std rand native:context_switch
DEPS_rustuv := std native:uv native:uv_support
DEPS_native := std
-DEPS_syntax := std term serialize collections
+DEPS_syntax := std term serialize collections log
DEPS_rustc := syntax native:rustllvm flate arena serialize sync getopts \
- collections time extra
+ collections time log
DEPS_rustdoc := rustc native:sundown serialize sync getopts collections \
test time
-DEPS_flate := std extra native:miniz
+DEPS_flate := std native:miniz
DEPS_arena := std collections
DEPS_glob := std
-DEPS_serialize := std collections
+DEPS_serialize := std collections log
DEPS_term := std collections
DEPS_semver := std
DEPS_uuid := std serialize rand
DEPS_fourcc := syntax std
DEPS_hexfloat := syntax std
DEPS_num := std rand
-DEPS_test := std extra collections getopts serialize term
+DEPS_test := std collections getopts serialize term time
DEPS_time := std serialize
DEPS_rand := std
+DEPS_url := std collections
+DEPS_workcache := std serialize collections log
+DEPS_log := std sync
TOOL_DEPS_compiletest := test green rustuv getopts
TOOL_DEPS_rustdoc := rustdoc native
DOCS := index tutorial guide-ffi guide-macros guide-lifetimes \
guide-tasks guide-container guide-pointers guide-testing \
guide-runtime complement-bugreport complement-cheatsheet \
- complement-lang-faq complement-project-faq rust rustdoc
+ complement-lang-faq complement-project-faq rust rustdoc \
+ guide-unsafe
PDF_DOCS := tutorial rust
// except according to those terms.
#[crate_type = "bin"];
+#[feature(phase)];
#[allow(non_camel_case_types)];
#[deny(warnings)];
+#[allow(deprecated_owned_vector)];
extern crate test;
extern crate getopts;
+#[phase(link, syntax)]
+extern crate log;
use std::os;
use std::io;
When this occurs, we must use Rust's destructors to provide safety and guarantee
the release of these resources (especially in the case of failure).
-As an example, we give a reimplementation of owned boxes by wrapping `malloc`
-and `free`:
-
-~~~~
-use std::cast;
-use std::libc::{c_void, size_t, malloc, free};
-use std::mem;
-use std::ptr;
-
-// Define a wrapper around the handle returned by the foreign code.
-// Unique<T> has the same semantics as ~T
-pub struct Unique<T> {
- // It contains a single raw, mutable pointer to the object in question.
- priv ptr: *mut T
-}
-
-// Implement methods for creating and using the values in the box.
-// NB: For simplicity and correctness, we require that T has kind Send
-// (owned boxes relax this restriction, and can contain managed (GC) boxes).
-// This is because, as implemented, the garbage collector would not know
-// about any shared boxes stored in the malloc'd region of memory.
-impl<T: Send> Unique<T> {
- pub fn new(value: T) -> Unique<T> {
- unsafe {
- let ptr = malloc(std::mem::size_of::<T>() as size_t) as *mut T;
- assert!(!ptr.is_null());
- // `*ptr` is uninitialized, and `*ptr = value` would attempt to destroy it
- // move_val_init moves a value into this memory without
- // attempting to drop the original value.
- mem::move_val_init(&mut *ptr, value);
- Unique{ptr: ptr}
- }
- }
-
- // the 'r lifetime results in the same semantics as `&*x` with ~T
- pub fn borrow<'r>(&'r self) -> &'r T {
- unsafe { cast::copy_lifetime(self, &*self.ptr) }
- }
-
- // the 'r lifetime results in the same semantics as `&mut *x` with ~T
- pub fn borrow_mut<'r>(&'r mut self) -> &'r mut T {
- unsafe { cast::copy_mut_lifetime(self, &mut *self.ptr) }
- }
-}
-
-// The key ingredient for safety, we associate a destructor with
-// Unique<T>, making the struct manage the raw pointer: when the
-// struct goes out of scope, it will automatically free the raw pointer.
-// NB: This is an unsafe destructor, because rustc will not normally
-// allow destructors to be associated with parametrized types, due to
-// bad interaction with managed boxes. (With the Send restriction,
-// we don't have this problem.)
-#[unsafe_destructor]
-impl<T: Send> Drop for Unique<T> {
- fn drop(&mut self) {
- unsafe {
- let x = mem::uninit(); // dummy value to swap in
- // We need to move the object out of the box, so that
- // the destructor is called (at the end of this scope.)
- ptr::replace(self.ptr, x);
- free(self.ptr as *mut c_void)
- }
- }
-}
-
-// A comparison between the built-in ~ and this reimplementation
-fn main() {
- {
- let mut x = ~5;
- *x = 10;
- } // `x` is freed here
-
- {
- let mut y = Unique::new(5);
- *y.borrow_mut() = 10;
- } // `y` is freed here
-}
-~~~~
-
# Callbacks from C code to Rust functions
Some external libraries require the usage of callbacks to report back their
fn main() {
let numbers = vec::from_fn(1000000, |_| rand::random::<f64>());
- println!("Inf-norm = {}", *numbers.iter().max().unwrap());
-
let numbers_arc = Arc::new(numbers);
for num in range(1u, 10) {
--- /dev/null
+% Writing Safe Unsafe and Low-Level Code
+
+# Introduction
+
+Rust aims to provide safe abstractions over the low-level details of
+the CPU and operating system, but sometimes one is forced to drop down
+and write code at that level (those abstractions have to be created
+somehow). This guide aims to provide an overview of the dangers and
+power one gets with Rust's unsafe subset.
+
+Rust provides an escape hatch in the form of the `unsafe { ... }`
+block which allows the programmer to dodge some of the compilers
+checks and do a wide range of operations, such as:
+
+- dereferencing [raw pointers](#raw-pointers)
+- calling a function via FFI ([covered by the FFI guide](guide-ffi.html))
+- casting between types bitwise (`transmute`, aka "reinterpret cast")
+- [inline assembly](#inline-assembly)
+
+Note that an `unsafe` block does not relax the rules about lifetimes
+of `&` and the freezing of borrowed data, it just allows the use of
+additional techniques for skirting the compiler's watchful eye. Any
+use of `unsafe` is the programmer saying "I know more than you" to the
+compiler, and, as such, the programmer should be very sure that they
+actually do know more about why that piece of code is valid.
+
+In general, one should try to minimize the amount of unsafe code in a
+code base; preferably by using the bare minimum `unsafe` blocks to
+build safe interfaces.
+
+> **Note**: the low-level details of the Rust language are still in
+> flux, and there is no guarantee of stability or backwards
+> compatibility. In particular, there may be changes that do not cause
+> compilation errors, but do cause semantic changes (such as invoking
+> undefined behaviour). As such, extreme care is required.
+
+# Pointers
+
+## References
+
+One of Rust's biggest goals as a language is ensuring memory safety,
+achieved in part via [the lifetime system](guide-lifetimes.html) which
+every `&` references has associated with it. This system is how the
+compiler can guarantee that every `&` reference is always valid, and,
+for example, never pointing to freed memory.
+
+These restrictions on `&` have huge advantages. However, there's no
+free lunch club. For example, `&` isn't a valid replacement for C's
+pointers, and so cannot be used for FFI, in general. Additionally,
+both immutable (`&`) and mutable (`&mut`) references have some
+aliasing and freezing guarantees, required for memory safety.
+
+In particular, if you have an `&T` reference, then the `T` must not be
+modified through that reference or any other reference. There are some
+standard library types, e.g. `Cell` and `RefCell`, that provide inner
+mutability by replacing compile time guarantees with dynamic checks at
+runtime.
+
+An `&mut` reference has a stronger requirement: when a object has an
+`&mut T` pointing into it, then that `&mut` reference must be the only
+such usable path to that object in the whole program. That is, an
+`&mut` cannot alias with any other references.
+
+Using `unsafe` code to incorrectly circumvent and violate these
+restrictions is undefined behaviour. For example, the following
+creates two aliasing `&mut` pointers, and is invalid.
+
+```
+use std::cast;
+let mut x: u8 = 1;
+
+let ref_1: &mut u8 = &mut x;
+let ref_2: &mut u8 = unsafe { cast::transmute_mut_region(ref_1) };
+
+// oops, ref_1 and ref_2 point to the same piece of data (x) and are
+// both usable
+*ref_1 = 10;
+*ref_2 = 20;
+```
+
+## Raw pointers
+
+Rust offers two additional pointer types "raw pointers", written as
+`*T` and `*mut T`. They're an approximation of C's `const T*` and `T*`
+respectively; indeed, one of their most common uses is for FFI,
+interfacing with external C libraries.
+
+Raw pointers have much fewer guarantees than other pointer types
+offered by the Rust language and libraries. For example, they
+
+- are not guaranteed to point to valid memory and are not even
+ guaranteed to be non-null (unlike both `~` and `&`);
+- do not have any automatic clean-up, unlike `~`, and so require
+ manual resource management;
+- are plain-old-data, that is, they don't move ownership, again unlike
+ `~`, hence the Rust compiler cannot protect against bugs like
+ use-after-free;
+- are considered sendable (if their contents is considered sendable),
+ so the compiler offers no assistance with ensuring their use is
+ thread-safe; for example, one can concurrently access a `*mut int`
+ from two threads without synchronization.
+- lack any form of lifetimes, unlike `&`, and so the compiler cannot
+ reason about dangling pointers; and
+- have no guarantees about aliasing or mutability other than mutation
+ not being allowed directly through a `*T`.
+
+Fortunately, they come with a redeeming feature: the weaker guarantees
+mean weaker restrictions. The missing restrictions make raw pointers
+appropriate as a building block for (carefully!) implementing things
+like smart pointers and vectors inside libraries. For example, `*`
+pointers are allowed to alias, allowing them to be used to write
+shared-ownership types like reference counted and garbage collected
+pointers, and even thread-safe shared memory types (`Rc` and the `Arc`
+types are both implemented entirely in Rust).
+
+There are two things that you are required to be careful about
+(i.e. require an `unsafe { ... }` block) with raw pointers:
+
+- dereferencing: they can have any value: so possible results include
+ a crash, a read of uninitialised memory, a use-after-free, or
+ reading data as normal (and one hopes happens).
+- pointer arithmetic via the `offset` [intrinsic](#intrinsics) (or
+ `.offset` method): this intrinsic uses so-called "in-bounds"
+ arithmetic, that is, it is only defined behaviour if the result is
+ inside (or one-byte-past-the-end) of the object from which the
+ original pointer came.
+
+The latter assumption allows the compiler to optimize more
+effectively. As can be seen, actually *creating* a raw pointer is not
+unsafe, and neither is converting to an integer.
+
+### References and raw pointers
+
+At runtime, a raw pointer `*` and a reference pointing to the same
+piece of data have an identical representation. In fact, an `&T`
+reference will implicitly coerce to an `*T` raw pointer in safe code
+and similarly for the `mut` variants (both coercions can be performed
+explicitly with, respectively, `value as *T` and `value as *mut T`).
+
+Going the opposite direction, from `*` to a reference `&`, is not
+safe. A `&T` is always valid, and so, at a minimum, the raw pointer
+`*T` has to be a valid to a valid instance of type `T`. Furthermore,
+the resulting pointer must satisfy the aliasing and mutability laws of
+references. The compiler assumes these properties are true for any
+references, no matter how they are created, and so any conversion from
+raw pointers is asserting that they hold. The programmer *must*
+guarantee this.
+
+The recommended method for the conversion is
+
+```
+let i: u32 = 1;
+// explicit cast
+let p_imm: *u32 = &i as *u32;
+let mut m: u32 = 2;
+// implicit coercion
+let p_mut: *mut u32 = &mut m;
+
+unsafe {
+ let ref_imm: &u32 = &*p_imm;
+ let ref_mut: &mut u32 = &mut *p_mut;
+}
+```
+
+The `&*x` dereferencing style is preferred to using a `transmute`.
+The latter is far more powerful than necessary, and the more
+restricted operation is harder to use incorrectly; for example, it
+requires that `x` is a pointer (unlike `transmute`).
+
+
+
+## Making the unsafe safe(r)
+
+There are various ways to expose a safe interface around some unsafe
+code:
+
+- store pointers privately (i.e. not in public fields of public
+ structs), so that you can see and control all reads and writes to
+ the pointer in one place.
+- use `assert!()` a lot: once you've thrown away the protection of the
+ compiler & type-system via `unsafe { ... }` you're left with just
+ your wits and your `assert!()`s, any bug is potentially exploitable.
+- implement the `Drop` for resource clean-up via a destructor, and use
+ RAII (Resource Acquisition Is Initialization). This reduces the need
+ for any manual memory management by users, and automatically ensures
+ that clean-up is always run, even when the task fails.
+- ensure that any data stored behind a raw pointer is destroyed at the
+ appropriate time.
+
+As an example, we give a reimplementation of owned boxes by wrapping
+`malloc` and `free`. Rust's move semantics and lifetimes mean this
+reimplementation is as safe as the built-in `~` type.
+
+```
+use std::libc::{c_void, size_t, malloc, free};
+use std::mem;
+use std::ptr;
+
+// Define a wrapper around the handle returned by the foreign code.
+// Unique<T> has the same semantics as ~T
+pub struct Unique<T> {
+ // It contains a single raw, mutable pointer to the object in question.
+ priv ptr: *mut T
+}
+
+// Implement methods for creating and using the values in the box.
+// NB: For simplicity and correctness, we require that T has kind Send
+// (owned boxes relax this restriction, and can contain managed (GC) boxes).
+// This is because, as implemented, the garbage collector would not know
+// about any shared boxes stored in the malloc'd region of memory.
+impl<T: Send> Unique<T> {
+ pub fn new(value: T) -> Unique<T> {
+ unsafe {
+ let ptr = malloc(std::mem::size_of::<T>() as size_t) as *mut T;
+ // we *need* valid pointer.
+ assert!(!ptr.is_null());
+ // `*ptr` is uninitialized, and `*ptr = value` would attempt to destroy it
+ // move_val_init moves a value into this memory without
+ // attempting to drop the original value.
+ mem::move_val_init(&mut *ptr, value);
+ Unique{ptr: ptr}
+ }
+ }
+
+ // the 'r lifetime results in the same semantics as `&*x` with ~T
+ pub fn borrow<'r>(&'r self) -> &'r T {
+ // By construction, self.ptr is valid
+ unsafe { &*self.ptr }
+ }
+
+ // the 'r lifetime results in the same semantics as `&mut *x` with ~T
+ pub fn borrow_mut<'r>(&'r mut self) -> &'r mut T {
+ unsafe { &mut*self.ptr }
+ }
+}
+
+// A key ingredient for safety, we associate a destructor with
+// Unique<T>, making the struct manage the raw pointer: when the
+// struct goes out of scope, it will automatically free the raw pointer.
+// NB: This is an unsafe destructor, because rustc will not normally
+// allow destructors to be associated with parametrized types, due to
+// bad interaction with managed boxes. (With the Send restriction,
+// we don't have this problem.)
+#[unsafe_destructor]
+impl<T: Send> Drop for Unique<T> {
+ fn drop(&mut self) {
+ unsafe {
+
+ // Copy the object out from the pointer onto the stack,
+ // where it is covered by normal Rust destructor semantics
+ // and cleans itself up, if necessary
+ ptr::read(self.ptr as *T);
+
+ // clean-up our allocation
+ free(self.ptr as *mut c_void)
+ }
+ }
+}
+
+// A comparison between the built-in ~ and this reimplementation
+fn main() {
+ {
+ let mut x = ~5;
+ *x = 10;
+ } // `x` is freed here
+
+ {
+ let mut y = Unique::new(5);
+ *y.borrow_mut() = 10;
+ } // `y` is freed here
+}
+```
+
+Notably, the only way to construct a `Unique` is via the `new`
+function, and this function ensures that the internal pointer is valid
+and hidden in the private field. The two `borrow` methods are safe
+because the compiler statically guarantees that objects are never used
+before creation or after destruction (unless you use some `unsafe`
+code...).
+
+# Inline assembly
+
+For extremely low-level manipulations and performance reasons, one
+might wish to control the CPU directly. Rust supports using inline
+assembly to do this via the `asm!` macro. The syntax roughly matches
+that of GCC & Clang:
+
+```ignore
+asm!(assembly template
+ : output operands
+ : input operands
+ : clobbers
+ : options
+ );
+```
+
+Any use of `asm` is feature gated (requires `#[feature(asm)];` on the
+crate to allow) and of course requires an `unsafe` block.
+
+> **Note**: the examples here are given in x86/x86-64 assembly, but all
+> platforms are supported.
+
+## Assembly template
+
+The `assembly template` is the only required parameter and must be a
+literal string (i.e `""`)
+
+```
+#[feature(asm)];
+
+#[cfg(target_arch = "x86")]
+#[cfg(target_arch = "x86_64")]
+fn foo() {
+ unsafe {
+ asm!("NOP");
+ }
+}
+
+// other platforms
+#[cfg(not(target_arch = "x86"),
+ not(target_arch = "x86_64"))]
+fn foo() { /* ... */ }
+
+fn main() {
+ // ...
+ foo();
+ // ...
+}
+```
+
+(The `feature(asm)` and `#[cfg]`s are omitted from now on.)
+
+Output operands, input operands, clobbers and options are all optional
+but you must add the right number of `:` if you skip them:
+
+```
+# #[feature(asm)];
+# #[cfg(target_arch = "x86")] #[cfg(target_arch = "x86_64")]
+# fn main() { unsafe {
+asm!("xor %eax, %eax"
+ :
+ :
+ : "eax"
+ );
+# } }
+```
+
+Whitespace also doesn't matter:
+
+```
+# #[feature(asm)];
+# #[cfg(target_arch = "x86")] #[cfg(target_arch = "x86_64")]
+# fn main() { unsafe {
+asm!("xor %eax, %eax" ::: "eax");
+# } }
+```
+
+## Operands
+
+Input and output operands follow the same format: `:
+"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand
+expressions must be mutable lvalues:
+
+```
+# #[feature(asm)];
+# #[cfg(target_arch = "x86")] #[cfg(target_arch = "x86_64")]
+fn add(a: int, b: int) -> int {
+ let mut c = 0;
+ unsafe {
+ asm!("add $2, $0"
+ : "=r"(c)
+ : "0"(a), "r"(b)
+ );
+ }
+ c
+}
+# #[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"))]
+# fn add(a: int, b: int) -> int { a + b }
+
+fn main() {
+ assert_eq!(add(3, 14159), 14162)
+}
+```
+
+## Clobbers
+
+Some instructions modify registers which might otherwise have held
+different values so we use the clobbers list to indicate to the
+compiler not to assume any values loaded into those registers will
+stay valid.
+
+```
+# #[feature(asm)];
+# #[cfg(target_arch = "x86")] #[cfg(target_arch = "x86_64")]
+# fn main() { unsafe {
+// Put the value 0x200 in eax
+asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax");
+# } }
+```
+
+Input and output registers need not be listed since that information
+is already communicated by the given constraints. Otherwise, any other
+registers used either implicitly or explicitly should be listed.
+
+If the assembly changes the condition code register `cc` should be
+specified as one of the clobbers. Similarly, if the assembly modifies
+memory, `memory` should also be specified.
+
+## Options
+
+The last section, `options` is specific to Rust. The format is comma
+separated literal strings (i.e `:"foo", "bar", "baz"`). It's used to
+specify some extra info about the inline assembly:
+
+Current valid options are:
+
+1. **volatile** - specifying this is analogous to `__asm__ __volatile__ (...)` in gcc/clang.
+2. **alignstack** - certain instructions expect the stack to be
+ aligned a certain way (i.e SSE) and specifying this indicates to
+ the compiler to insert its usual stack alignment code
+3. **intel** - use intel syntax instead of the default AT&T.
+
+# Avoiding the standard library
+
+By default, `std` is linked to every Rust crate. In some contexts,
+this is undesirable, and can be avoided with the `#[no_std];`
+attribute attached to the crate.
+
+```ignore
+# // FIXME #12903: linking failures due to no_std
+// the minimal library
+#[crate_type="lib"];
+#[no_std];
+
+# // fn main() {} tricked you, rustdoc!
+```
+
+Obviously there's more to life than just libraries: one can use
+`#[no_std]` with an executable, controlling the entry point is
+possible in two ways: the `#[start]` attribute, or overriding the
+default shim for the C `main` function with your own.
+
+The function marked `#[start]` is passed the command line parameters
+in the same format as a C:
+
+```ignore
+# // FIXME #12903: linking failures due to no_std
+#[no_std];
+
+extern "rust-intrinsic" { fn abort() -> !; }
+#[no_mangle] pub extern fn rust_stack_exhausted() {
+ unsafe { abort() }
+}
+
+#[start]
+fn start(_argc: int, _argv: **u8) -> int {
+ 0
+}
+
+# // fn main() {} tricked you, rustdoc!
+```
+
+To override the compiler-inserted `main` shim, one has to disable it
+with `#[no_main];` and then create the appropriate symbol with the
+correct ABI and the correct name, which requires overriding the
+compiler's name mangling too:
+
+```ignore
+# // FIXME #12903: linking failures due to no_std
+#[no_std];
+#[no_main];
+
+extern "rust-intrinsic" { fn abort() -> !; }
+#[no_mangle] pub extern fn rust_stack_exhausted() {
+ unsafe { abort() }
+}
+
+#[no_mangle] // ensure that this symbol is called `main` in the output
+extern "C" fn main(_argc: int, _argv: **u8) -> int {
+ 0
+}
+
+# // fn main() {} tricked you, rustdoc!
+```
+
+
+Unfortunately the Rust compiler assumes that symbols with certain
+names exist; and these have to be defined (or linked in). This is the
+purpose of the `rust_stack_exhausted`: it is called when a function
+detects that it will overflow its stack. The example above uses the
+`abort` intrinsic which ensures that execution halts.
+
+# Interacting with the compiler internals
+
+> **Note**: this section is specific to the `rustc` compiler; these
+> parts of the language may never be full specified and so details may
+> differ wildly between implementations (and even versions of `rustc`
+> itself).
+>
+> Furthermore, this is just an overview; the best form of
+> documentation for specific instances of these features are their
+> definitions and uses in `std`.
+
+The Rust language currently has two orthogonal mechanisms for allowing
+libraries to interact directly with the compiler and vice versa:
+
+- intrinsics, functions built directly into the compiler providing
+ very basic low-level functionality,
+- lang-items, special functions, types and traits in libraries marked
+ with specific `#[lang]` attributes
+
+## Intrinsics
+
+These are imported as if they were FFI functions, with the special
+`rust-intrinsic` ABI. For example, if one was in a freestanding
+context, but wished to be able to `transmute` between types, and
+perform efficient pointer arithmetic, one would import those functions
+via a declaration like
+
+```
+extern "rust-intrinsic" {
+ fn transmute<T, U>(x: T) -> U;
+
+ fn offset<T>(dst: *T, offset: int) -> *T;
+}
+```
+
+As with any other FFI functions, these are always `unsafe` to call.
+
+## Lang items
+
+The `rustc` compiler has certain pluggable operations, that is,
+functionality that isn't hard-coded into the language, but is
+implemented in libraries, with a special marker to tell the compiler
+it exists. The marker is the attribute `#[lang="..."]` and there are
+various different values of `...`, i.e. various different "lang
+items".
+
+For example, `~` pointers require two lang items, one for allocation
+and one for deallocation. A freestanding program that uses the `~`
+sugar for dynamic allocations via `malloc` and `free`:
+
+```ignore
+# // FIXME #12903: linking failures due to no_std
+#[no_std];
+
+#[allow(ctypes)] // `uint` == `size_t` on Rust's platforms
+extern {
+ fn malloc(size: uint) -> *mut u8;
+ fn free(ptr: *mut u8);
+
+ fn abort() -> !;
+}
+
+#[no_mangle] pub extern fn rust_stack_exhausted() {
+ unsafe { abort() }
+}
+
+#[lang="exchange_malloc"]
+unsafe fn allocate(size: uint) -> *mut u8 {
+ let p = malloc(size);
+
+ // malloc failed
+ if p as uint == 0 {
+ abort();
+ }
+
+ p
+}
+#[lang="exchange_free"]
+unsafe fn deallocate(ptr: *mut u8) {
+ free(ptr)
+}
+
+#[start]
+fn main(_argc: int, _argv: **u8) -> int {
+ let _x = ~1;
+
+ 0
+}
+
+# // fn main() {} tricked you, rustdoc!
+```
+
+Note the use of `abort`: the `exchange_malloc` lang item is assumed to
+return a valid pointer, and so needs to do the check
+internally.
+
+Other features provided by lang items include:
+
+- overloadable operators via traits: the traits corresponding to the
+ `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all
+ marked with lang items; those specific four are `eq`, `ord`,
+ `deref`, and `add` respectively.
+- stack unwinding and general failure; the `eh_personality`, `fail_`
+ and `fail_bounds_checks` lang items.
+- the traits in `std::kinds` used to indicate types that satisfy
+ various kinds; lang items `send`, `freeze` and `pod`.
+- the marker types and variance indicators found in
+ `std::kinds::markers`; lang items `covariant_type`,
+ `contravariant_lifetime`, `no_freeze_bound`, etc.
+
+Lang items are loaded lazily by the compiler; e.g. if one never uses
+`~` then there is no need to define functions for `exchange_malloc`
+and `exchange_free`. `rustc` will emit an error when an item is needed
+but not found in the current crate or any that it depends on.
* [Containers and Iterators](guide-container.html)
* [Tasks and Communication](guide-tasks.html)
* [Foreign Function Interface](guide-ffi.html)
+* [Writing Safe Unsafe and Low-Level Code](guide-unsafe.html)
* [Macros](guide-macros.html)
* [Testing](guide-testing.html)
* [Rust's Runtime](guide-runtime.html)
* [The `arena` allocation library](arena/index.html)
* [The `collections` library](collections/index.html)
-* [The `extra` library of extra stuff](extra/index.html)
* [The `flate` compression library](flate/index.html)
* [The `fourcc` four-character code library](fourcc/index.html)
* [The `getopts` argument parsing library](getopts/index.html)
* [The `test` library containing the unit-testing & micro-benchmark framework](test/index.html)
* [The `time` library](time/index.html)
* [The `uuid` 128-bit universally unique identifier library](uuid/index.html)
+* [The `url` library](url/index.html)
+* [The `workcache` library](workcache/index.html)
+* [The `log` library](log/index.html)
# Tooling
~~~~ {.ignore}
extern crate pcre;
-extern crate extra; // equivalent to: extern crate extra = "extra";
+extern crate std; // equivalent to: extern crate std = "std";
-extern crate rustextra = "extra"; // linking to 'extra' under another name
+extern crate ruststd = "std"; // linking to 'std' under another name
extern crate foo = "some/where/rust-foo#foo:1.0"; // a full package ID for external tools
~~~~
~~~~
fn my_err(s: &str) -> ! {
- info!("{}", s);
+ println!("{}", s);
fail!();
}
~~~~
that demonstrates all four of them:
~~~~
+#[feature(phase)];
+#[phase(syntax, link)] extern crate log;
+
fn main() {
error!("This is an error log")
warn!("This is a warn log")
~~~~
let mytup: (int, int, f64) = (10, 20, 30.0);
match mytup {
- (a, b, c) => info!("{}", a + b + (c as int))
+ (a, b, c) => println!("{}", a + b + (c as int))
}
~~~~
struct MyTup(int, int, f64);
let mytup: MyTup = MyTup(10, 20, 30.0);
match mytup {
- MyTup(a, b, c) => info!("{}", a + b + (c as int))
+ MyTup(a, b, c) => println!("{}", a + b + (c as int))
}
~~~~
// proc is the closure which will be spawned.
spawn(proc() {
- debug!("I'm a new task")
+ println!("I'm a new task")
});
~~~~
[stddoc]: std/index.html
-## The extra library
-
-Rust ships with crates such as the [extra library], an accumulation of useful things,
-that are however not important enough to deserve a place in the standard
-library. You can link to a library such as `extra` with an `extern crate extra;`.
-
-[extra library]: extra/index.html
-
-Right now `extra` contains those definitions directly, but in the future it will likely just
-re-export a bunch of 'officially blessed' crates that get managed with a package manager.
-
# What next?
Now that you know the essentials, check out any of the additional
#[feature(globs, macro_rules, struct_variant, managed_boxes)];
#[allow(warnings)];
extern crate collections;
-extern crate extra;
"""
)
for t in stage2_tests:
"""
// AUTO-GENERATED FILE: DO NOT EDIT
#[feature(globs, managed_boxes)];
-extern crate extra;
extern crate run_pass_stage2;
use run_pass_stage2::*;
use std::io;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
{error_deriving}
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
#[allow(missing_doc)];
#[feature(managed_boxes)];
+#[allow(deprecated_owned_vector)];
extern crate collections;
// except according to those terms.
//! Unordered containers, implemented as hash-tables (`HashSet` and `HashMap` types)
-//!
-//! The tables use a keyed hash with new random keys generated for each container, so the ordering
-//! of a set of keys in a hash table is randomized.
-//!
-//! This is currently implemented with robin hood hashing, as described in [1][2][3].
-//!
-//! # Example
-//!
-//! ```rust
-//! use collections::HashMap;
-//!
-//! // type inference lets us omit an explicit type signature (which
-//! // would be `HashMap<&str, &str>` in this example).
-//! let mut book_reviews = HashMap::new();
-//!
-//! // review some books.
-//! book_reviews.insert("Adventures of Hucklebury Fin", "My favorite book.");
-//! book_reviews.insert("Grimms' Fairy Tales", "Masterpiece.");
-//! book_reviews.insert("Pride and Prejudice", "Very enjoyable.");
-//! book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot.");
-//!
-//! // check for a specific one.
-//! if !book_reviews.contains_key(& &"Les Misérables") {
-//! println!("We've got {} reviews, but Les Misérables ain't one.",
-//! book_reviews.len());
-//! }
-//!
-//! // oops, this review has a lot of spelling mistakes, let's delete it.
-//! book_reviews.remove(& &"The Adventures of Sherlock Holmes");
-//!
-//! // look up the values associated with some keys.
-//! let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
-//! for book in to_find.iter() {
-//! match book_reviews.find(book) {
-//! Some(review) => println!("{}: {}", *book, *review),
-//! None => println!("{} is unreviewed.", *book)
-//! }
-//! }
-//!
-//! // iterate over everything.
-//! for (book, review) in book_reviews.iter() {
-//! println!("{}: \"{}\"", *book, *review);
-//! }
-//! ```
-//!
-//! Relevant papers/articles:
-//!
-//! [1]: Pedro Celis. ["Robin Hood Hashing"](https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf)
-//! [2]: (http://codecapsule.com/2013/11/11/robin-hood-hashing/)
-//! [3]: (http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/)
use std::container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
use std::clone::Clone;
// `table::RawTable::new`, but I'm not confident it works for all sane alignments,
// especially if a type needs more alignment than `malloc` provides.
-/// A hash map implementation which uses linear probing with Robin Hood bucket
-/// stealing.
+/// A hash map implementation which uses linear probing with Robin
+/// Hood bucket stealing.
///
/// The hashes are all keyed by the task-local random number generator
-/// on creation by default. This can be overriden with one of the constructors.
+/// on creation by default, this means the ordering of the keys is
+/// randomized, but makes the tables more resistant to
+/// denial-of-service attacks (Hash DoS). This behaviour can be
+/// overriden with one of the constructors.
///
/// It is required that the keys implement the `Eq` and `Hash` traits, although
/// this can frequently be achieved by using `#[deriving(Eq, Hash)]`.
+///
+/// Relevant papers/articles:
+///
+/// 1. Pedro Celis. ["Robin Hood Hashing"](https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf)
+/// 2. Emmanuel Goossaert. ["Robin Hood
+/// hashing"](http://codecapsule.com/2013/11/11/robin-hood-hashing/)
+/// 3. Emmanuel Goossaert. ["Robin Hood hashing: backward shift
+/// deletion"](http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/)
+///
+/// # Example
+///
+/// ```rust
+/// use collections::HashMap;
+///
+/// // type inference lets us omit an explicit type signature (which
+/// // would be `HashMap<&str, &str>` in this example).
+/// let mut book_reviews = HashMap::new();
+///
+/// // review some books.
+/// book_reviews.insert("Adventures of Hucklebury Fin", "My favorite book.");
+/// book_reviews.insert("Grimms' Fairy Tales", "Masterpiece.");
+/// book_reviews.insert("Pride and Prejudice", "Very enjoyable.");
+/// book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot.");
+///
+/// // check for a specific one.
+/// if !book_reviews.contains_key(& &"Les Misérables") {
+/// println!("We've got {} reviews, but Les Misérables ain't one.",
+/// book_reviews.len());
+/// }
+///
+/// // oops, this review has a lot of spelling mistakes, let's delete it.
+/// book_reviews.remove(& &"The Adventures of Sherlock Holmes");
+///
+/// // look up the values associated with some keys.
+/// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
+/// for book in to_find.iter() {
+/// match book_reviews.find(book) {
+/// Some(review) => println!("{}: {}", *book, *review),
+/// None => println!("{} is unreviewed.", *book)
+/// }
+/// }
+///
+/// // iterate over everything.
+/// for (book, review) in book_reviews.iter() {
+/// println!("{}: \"{}\"", *book, *review);
+/// }
+/// ```
#[deriving(Clone)]
pub struct HashMap<K, V, H = sip::SipHasher> {
// All hashes are keyed on these values, to prevent hash collision attacks.
/// so we have some sort of upper bound on the number of probes to do.
///
/// 'hash', 'k', and 'v' are the elements to robin hood into the hashtable.
- fn robin_hood(&mut self, index: table::FullIndex, dib_param: uint,
- hash: table::SafeHash, k: K, v: V) {
- let (old_hash, old_key, old_val) = {
- let (old_hash_ref, old_key_ref, old_val_ref) = self.table.read_all_mut(&index);
-
- let old_hash = replace(old_hash_ref, hash);
- let old_key = replace(old_key_ref, k);
- let old_val = replace(old_val_ref, v);
-
- (old_hash, old_key, old_val)
- };
-
- let mut probe = self.probe_next(index.raw_index());
-
- for dib in range(dib_param + 1, self.table.size()) {
- let full_index = match self.table.peek(probe) {
- table::Empty(idx) => {
- // Finally. A hole!
- self.table.put(idx, old_hash, old_key, old_val);
- return;
- },
- table::Full(idx) => idx
+ fn robin_hood(&mut self, mut index: table::FullIndex, mut dib_param: uint,
+ mut hash: table::SafeHash, mut k: K, mut v: V) {
+ 'outer: loop {
+ let (old_hash, old_key, old_val) = {
+ let (old_hash_ref, old_key_ref, old_val_ref) =
+ self.table.read_all_mut(&index);
+
+ let old_hash = replace(old_hash_ref, hash);
+ let old_key = replace(old_key_ref, k);
+ let old_val = replace(old_val_ref, v);
+
+ (old_hash, old_key, old_val)
};
- let probe_dib = self.bucket_distance(&full_index);
+ let mut probe = self.probe_next(index.raw_index());
+
+ for dib in range(dib_param + 1, self.table.size()) {
+ let full_index = match self.table.peek(probe) {
+ table::Empty(idx) => {
+ // Finally. A hole!
+ self.table.put(idx, old_hash, old_key, old_val);
+ return;
+ },
+ table::Full(idx) => idx
+ };
+
+ let probe_dib = self.bucket_distance(&full_index);
+
+ // Robin hood! Steal the spot.
+ if probe_dib < dib {
+ index = full_index;
+ dib_param = probe_dib;
+ hash = old_hash;
+ k = old_key;
+ v = old_val;
+ continue 'outer;
+ }
- if probe_dib < dib {
- // Robin hood! Steal the spot. This had better be tail call.
- return self.robin_hood(full_index, probe_dib, old_hash, old_key, old_val);
+ probe = self.probe_next(probe);
}
- probe = self.probe_next(probe);
+ fail!("HashMap fatal error: 100% load factor?");
}
-
- fail!("HashMap fatal error: 100% load factor?");
}
/// Manually insert a pre-hashed key-value pair, without first checking
#[cfg(test)]
mod test_set {
- use super::HashMap;
use super::HashSet;
use std::container::Container;
use std::vec::ImmutableEqVector;
mod bench {
extern crate test;
use self::test::BenchHarness;
- use std::iter;
use std::iter::{range_inclusive};
#[bench]
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
-#[feature(macro_rules, managed_boxes, default_type_params)];
+#[feature(macro_rules, managed_boxes, default_type_params, phase)];
// NOTE remove the following two attributes after the next snapshot.
#[allow(unrecognized_lint)];
#[allow(default_type_param_usage)];
+#[allow(deprecated_owned_vector)];
extern crate rand;
#[cfg(test)] extern crate test;
+#[cfg(test)] #[phase(syntax, link)] extern crate log;
pub use bitv::Bitv;
pub use btree::BTree;
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
- * Library to interface with chunks of memory allocated in C.
- *
- * It is often desirable to safely interface with memory allocated from C,
- * encapsulating the unsafety into allocation and destruction time. Indeed,
- * allocating memory externally is currently the only way to give Rust shared
- * mut state with C programs that keep their own references; vectors are
- * unsuitable because they could be reallocated or moved at any time, and
- * importing C memory into a vector takes a one-time snapshot of the memory.
- *
- * This module simplifies the usage of such external blocks of memory. Memory
- * is encapsulated into an opaque object after creation; the lifecycle of the
- * memory can be optionally managed by Rust, if an appropriate destructor
- * closure is provided. Safety is ensured by bounds-checking accesses, which
- * are marshalled through get and set functions.
- *
- * There are three unsafe functions: the two constructors, and the
- * unwrap method. The constructors are unsafe for the
- * obvious reason (they act on a pointer that cannot be checked inside the
- * method), but `unwrap()` is somewhat more subtle in its unsafety.
- * It returns the contained pointer, but at the same time destroys the CVec
- * without running its destructor. This can be used to pass memory back to
- * C, but care must be taken that the ownership of underlying resources are
- * handled correctly, i.e. that allocated memory is eventually freed
- * if necessary.
- */
-
-use std::cast;
-use std::ptr;
-use std::raw;
-
-/**
- * The type representing a foreign chunk of memory
- */
-pub struct CVec<T> {
- priv base: *mut T,
- priv len: uint,
- priv rsrc: DtorRes,
-}
-
-struct DtorRes {
- dtor: Option<proc()>,
-}
-
-#[unsafe_destructor]
-impl Drop for DtorRes {
- fn drop(&mut self) {
- let dtor = self.dtor.take();
- match dtor {
- None => (),
- Some(f) => f()
- }
- }
-}
-
-impl DtorRes {
- fn new(dtor: Option<proc()>) -> DtorRes {
- DtorRes {
- dtor: dtor,
- }
- }
-}
-
-impl <T> CVec<T> {
- /**
- * Create a `CVec` from a raw pointer to a buffer with a given length.
- *
- * Fails if the given pointer is null.
- *
- * # Arguments
- *
- * * base - A raw pointer to a buffer
- * * len - The number of elements in the buffer
- */
- pub unsafe fn new(base: *mut T, len: uint) -> CVec<T> {
- assert!(base != ptr::mut_null());
- CVec {
- base: base,
- len: len,
- rsrc: DtorRes::new(None)
- }
- }
-
- /**
- * Create a `CVec` from a foreign buffer, with a given length,
- * and a function to run upon destruction.
- *
- * Fails if the given pointer is null.
- *
- * # Arguments
- *
- * * base - A foreign pointer to a buffer
- * * len - The number of elements in the buffer
- * * dtor - A proc to run when the value is destructed, useful
- * for freeing the buffer, etc.
- */
- pub unsafe fn new_with_dtor(base: *mut T, len: uint, dtor: proc()) -> CVec<T> {
- assert!(base != ptr::mut_null());
- CVec {
- base: base,
- len: len,
- rsrc: DtorRes::new(Some(dtor))
- }
- }
-
- /// View the stored data as a slice.
- pub fn as_slice<'a>(&'a self) -> &'a [T] {
- unsafe {
- cast::transmute(raw::Slice { data: self.base as *T, len: self.len })
- }
- }
-
- /// View the stored data as a mutable slice.
- pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
- unsafe {
- cast::transmute(raw::Slice { data: self.base as *T, len: self.len })
- }
- }
-
- /**
- * Retrieves an element at a given index
- *
- * Fails if `ofs` is greater or equal to the length of the vector
- */
- pub fn get<'a>(&'a self, ofs: uint) -> &'a T {
- assert!(ofs < self.len);
- unsafe {
- &*self.base.offset(ofs as int)
- }
- }
-
- /**
- * Retrieves a mutable element at a given index
- *
- * Fails if `ofs` is greater or equal to the length of the vector
- */
- pub fn get_mut<'a>(&'a mut self, ofs: uint) -> &'a mut T {
- assert!(ofs < self.len);
- unsafe {
- &mut *self.base.offset(ofs as int)
- }
- }
-
- /**
- * Unwrap the pointer without running the destructor
- *
- * This method retrieves the underlying pointer, and in the process
- * destroys the CVec but without running the destructor. A use case
- * would be transferring ownership of the buffer to a C function, as
- * in this case you would not want to run the destructor.
- *
- * Note that if you want to access the underlying pointer without
- * cancelling the destructor, you can simply call `transmute` on the return
- * value of `get(0)`.
- */
- pub unsafe fn unwrap(mut self) -> *mut T {
- self.rsrc.dtor = None;
- self.base
- }
-}
-
-impl <T> Container for CVec<T> {
- /// Returns the length of the vector
- fn len(&self) -> uint { self.len }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- use std::libc::*;
- use std::libc;
- use std::ptr;
- use std::rt::global_heap::malloc_raw;
-
- fn malloc(n: uint) -> CVec<u8> {
- unsafe {
- let mem = malloc_raw(n);
-
- CVec::new_with_dtor(mem as *mut u8, n,
- proc() { libc::free(mem as *mut c_void); })
- }
- }
-
- #[test]
- fn test_basic() {
- let mut cv = malloc(16);
-
- *cv.get_mut(3) = 8;
- *cv.get_mut(4) = 9;
- assert_eq!(*cv.get(3), 8);
- assert_eq!(*cv.get(4), 9);
- assert_eq!(cv.len(), 16);
- }
-
- #[test]
- #[should_fail]
- fn test_fail_at_null() {
- unsafe {
- CVec::new(ptr::mut_null::<u8>(), 9);
- }
- }
-
- #[test]
- #[should_fail]
- fn test_overrun_get() {
- let cv = malloc(16);
-
- cv.get(17);
- }
-
- #[test]
- #[should_fail]
- fn test_overrun_set() {
- let mut cv = malloc(16);
-
- *cv.get_mut(17) = 0;
- }
-
- #[test]
- fn test_unwrap() {
- unsafe {
- let cv = CVec::new_with_dtor(1 as *mut int, 0,
- proc() { fail!("Don't run this destructor!") });
- let p = cv.unwrap();
- assert_eq!(p, 1 as *mut int);
- }
- }
-
-}
+++ /dev/null
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
-
-Rust extras.
-
-The `extra` crate is a set of useful modules for a variety of
-purposes, including collections, numerics, I/O, serialization,
-and concurrency.
-
-Rust extras are part of the standard Rust distribution.
-
-*/
-
-#[crate_id = "extra#0.10-pre"];
-#[comment = "Rust extras"];
-#[license = "MIT/ASL2"];
-#[crate_type = "rlib"];
-#[crate_type = "dylib"];
-#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
- html_favicon_url = "http://www.rust-lang.org/favicon.ico",
- html_root_url = "http://static.rust-lang.org/doc/master")];
-
-#[feature(macro_rules, globs, managed_boxes, asm, default_type_params)];
-
-#[deny(non_camel_case_types)];
-#[deny(missing_doc)];
-
-extern crate collections;
-extern crate rand;
-extern crate serialize;
-extern crate sync;
-extern crate time;
-
-// Utility modules
-pub mod c_vec;
-pub mod url;
-pub mod tempfile;
-pub mod workcache;
-pub mod stats;
-
-#[cfg(unicode)]
-mod unicode;
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[allow(missing_doc)];
-
-use std::hash::Hash;
-use std::io;
-use std::mem;
-use std::num;
-use collections::hashmap;
-
-// NB: this can probably be rewritten in terms of num::Num
-// to be less f64-specific.
-
-fn f64_cmp(x: f64, y: f64) -> Ordering {
- // arbitrarily decide that NaNs are larger than everything.
- if y.is_nan() {
- Less
- } else if x.is_nan() {
- Greater
- } else if x < y {
- Less
- } else if x == y {
- Equal
- } else {
- Greater
- }
-}
-
-fn f64_sort(v: &mut [f64]) {
- v.sort_by(|x: &f64, y: &f64| f64_cmp(*x, *y));
-}
-
-/// Trait that provides simple descriptive statistics on a univariate set of numeric samples.
-pub trait Stats {
-
- /// Sum of the samples.
- ///
- /// Note: this method sacrifices performance at the altar of accuracy
- /// Depends on IEEE-754 arithmetic guarantees. See proof of correctness at:
- /// ["Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates"]
- /// (http://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps)
- /// *Discrete & Computational Geometry 18*, 3 (Oct 1997), 305-363, Shewchuk J.R.
- fn sum(self) -> f64;
-
- /// Minimum value of the samples.
- fn min(self) -> f64;
-
- /// Maximum value of the samples.
- fn max(self) -> f64;
-
- /// Arithmetic mean (average) of the samples: sum divided by sample-count.
- ///
- /// See: https://en.wikipedia.org/wiki/Arithmetic_mean
- fn mean(self) -> f64;
-
- /// Median of the samples: value separating the lower half of the samples from the higher half.
- /// Equal to `self.percentile(50.0)`.
- ///
- /// See: https://en.wikipedia.org/wiki/Median
- fn median(self) -> f64;
-
- /// Variance of the samples: bias-corrected mean of the squares of the differences of each
- /// sample from the sample mean. Note that this calculates the _sample variance_ rather than the
- /// population variance, which is assumed to be unknown. It therefore corrects the `(n-1)/n`
- /// bias that would appear if we calculated a population variance, by dividing by `(n-1)` rather
- /// than `n`.
- ///
- /// See: https://en.wikipedia.org/wiki/Variance
- fn var(self) -> f64;
-
- /// Standard deviation: the square root of the sample variance.
- ///
- /// Note: this is not a robust statistic for non-normal distributions. Prefer the
- /// `median_abs_dev` for unknown distributions.
- ///
- /// See: https://en.wikipedia.org/wiki/Standard_deviation
- fn std_dev(self) -> f64;
-
- /// Standard deviation as a percent of the mean value. See `std_dev` and `mean`.
- ///
- /// Note: this is not a robust statistic for non-normal distributions. Prefer the
- /// `median_abs_dev_pct` for unknown distributions.
- fn std_dev_pct(self) -> f64;
-
- /// Scaled median of the absolute deviations of each sample from the sample median. This is a
- /// robust (distribution-agnostic) estimator of sample variability. Use this in preference to
- /// `std_dev` if you cannot assume your sample is normally distributed. Note that this is scaled
- /// by the constant `1.4826` to allow its use as a consistent estimator for the standard
- /// deviation.
- ///
- /// See: http://en.wikipedia.org/wiki/Median_absolute_deviation
- fn median_abs_dev(self) -> f64;
-
- /// Median absolute deviation as a percent of the median. See `median_abs_dev` and `median`.
- fn median_abs_dev_pct(self) -> f64;
-
- /// Percentile: the value below which `pct` percent of the values in `self` fall. For example,
- /// percentile(95.0) will return the value `v` such that 95% of the samples `s` in `self`
- /// satisfy `s <= v`.
- ///
- /// Calculated by linear interpolation between closest ranks.
- ///
- /// See: http://en.wikipedia.org/wiki/Percentile
- fn percentile(self, pct: f64) -> f64;
-
- /// Quartiles of the sample: three values that divide the sample into four equal groups, each
- /// with 1/4 of the data. The middle value is the median. See `median` and `percentile`. This
- /// function may calculate the 3 quartiles more efficiently than 3 calls to `percentile`, but
- /// is otherwise equivalent.
- ///
- /// See also: https://en.wikipedia.org/wiki/Quartile
- fn quartiles(self) -> (f64,f64,f64);
-
- /// Inter-quartile range: the difference between the 25th percentile (1st quartile) and the 75th
- /// percentile (3rd quartile). See `quartiles`.
- ///
- /// See also: https://en.wikipedia.org/wiki/Interquartile_range
- fn iqr(self) -> f64;
-}
-
-/// Extracted collection of all the summary statistics of a sample set.
-#[deriving(Clone, Eq)]
-#[allow(missing_doc)]
-pub struct Summary {
- sum: f64,
- min: f64,
- max: f64,
- mean: f64,
- median: f64,
- var: f64,
- std_dev: f64,
- std_dev_pct: f64,
- median_abs_dev: f64,
- median_abs_dev_pct: f64,
- quartiles: (f64,f64,f64),
- iqr: f64,
-}
-
-impl Summary {
-
- /// Construct a new summary of a sample set.
- pub fn new(samples: &[f64]) -> Summary {
- Summary {
- sum: samples.sum(),
- min: samples.min(),
- max: samples.max(),
- mean: samples.mean(),
- median: samples.median(),
- var: samples.var(),
- std_dev: samples.std_dev(),
- std_dev_pct: samples.std_dev_pct(),
- median_abs_dev: samples.median_abs_dev(),
- median_abs_dev_pct: samples.median_abs_dev_pct(),
- quartiles: samples.quartiles(),
- iqr: samples.iqr()
- }
- }
-}
-
-impl<'a> Stats for &'a [f64] {
-
- // FIXME #11059 handle NaN, inf and overflow
- fn sum(self) -> f64 {
- let mut partials : ~[f64] = ~[];
-
- for &mut x in self.iter() {
- let mut j = 0;
- // This inner loop applies `hi`/`lo` summation to each
- // partial so that the list of partial sums remains exact.
- for i in range(0, partials.len()) {
- let mut y = partials[i];
- if num::abs(x) < num::abs(y) {
- mem::swap(&mut x, &mut y);
- }
- // Rounded `x+y` is stored in `hi` with round-off stored in
- // `lo`. Together `hi+lo` are exactly equal to `x+y`.
- let hi = x + y;
- let lo = y - (hi - x);
- if lo != 0f64 {
- partials[j] = lo;
- j += 1;
- }
- x = hi;
- }
- if j >= partials.len() {
- partials.push(x);
- } else {
- partials[j] = x;
- partials.truncate(j+1);
- }
- }
- partials.iter().fold(0.0, |p, q| p + *q)
- }
-
- fn min(self) -> f64 {
- assert!(self.len() != 0);
- self.iter().fold(self[0], |p, q| p.min(*q))
- }
-
- fn max(self) -> f64 {
- assert!(self.len() != 0);
- self.iter().fold(self[0], |p, q| p.max(*q))
- }
-
- fn mean(self) -> f64 {
- assert!(self.len() != 0);
- self.sum() / (self.len() as f64)
- }
-
- fn median(self) -> f64 {
- self.percentile(50.0)
- }
-
- fn var(self) -> f64 {
- if self.len() < 2 {
- 0.0
- } else {
- let mean = self.mean();
- let mut v = 0.0;
- for s in self.iter() {
- let x = *s - mean;
- v += x*x;
- }
- // NB: this is _supposed to be_ len-1, not len. If you
- // change it back to len, you will be calculating a
- // population variance, not a sample variance.
- v/((self.len()-1) as f64)
- }
- }
-
- fn std_dev(self) -> f64 {
- self.var().sqrt()
- }
-
- fn std_dev_pct(self) -> f64 {
- (self.std_dev() / self.mean()) * 100.0
- }
-
- fn median_abs_dev(self) -> f64 {
- let med = self.median();
- let abs_devs = self.map(|&v| num::abs(med - v));
- // This constant is derived by smarter statistics brains than me, but it is
- // consistent with how R and other packages treat the MAD.
- abs_devs.median() * 1.4826
- }
-
- fn median_abs_dev_pct(self) -> f64 {
- (self.median_abs_dev() / self.median()) * 100.0
- }
-
- fn percentile(self, pct: f64) -> f64 {
- let mut tmp = self.to_owned();
- f64_sort(tmp);
- percentile_of_sorted(tmp, pct)
- }
-
- fn quartiles(self) -> (f64,f64,f64) {
- let mut tmp = self.to_owned();
- f64_sort(tmp);
- let a = percentile_of_sorted(tmp, 25.0);
- let b = percentile_of_sorted(tmp, 50.0);
- let c = percentile_of_sorted(tmp, 75.0);
- (a,b,c)
- }
-
- fn iqr(self) -> f64 {
- let (a,_,c) = self.quartiles();
- c - a
- }
-}
-
-
-// Helper function: extract a value representing the `pct` percentile of a sorted sample-set, using
-// linear interpolation. If samples are not sorted, return nonsensical value.
-fn percentile_of_sorted(sorted_samples: &[f64],
- pct: f64) -> f64 {
- assert!(sorted_samples.len() != 0);
- if sorted_samples.len() == 1 {
- return sorted_samples[0];
- }
- assert!(0.0 <= pct);
- assert!(pct <= 100.0);
- if pct == 100.0 {
- return sorted_samples[sorted_samples.len() - 1];
- }
- let rank = (pct / 100.0) * ((sorted_samples.len() - 1) as f64);
- let lrank = rank.floor();
- let d = rank - lrank;
- let n = lrank as uint;
- let lo = sorted_samples[n];
- let hi = sorted_samples[n+1];
- lo + (hi - lo) * d
-}
-
-
-/// Winsorize a set of samples, replacing values above the `100-pct` percentile and below the `pct`
-/// percentile with those percentiles themselves. This is a way of minimizing the effect of
-/// outliers, at the cost of biasing the sample. It differs from trimming in that it does not
-/// change the number of samples, just changes the values of those that are outliers.
-///
-/// See: http://en.wikipedia.org/wiki/Winsorising
-pub fn winsorize(samples: &mut [f64], pct: f64) {
- let mut tmp = samples.to_owned();
- f64_sort(tmp);
- let lo = percentile_of_sorted(tmp, pct);
- let hi = percentile_of_sorted(tmp, 100.0-pct);
- for samp in samples.mut_iter() {
- if *samp > hi {
- *samp = hi
- } else if *samp < lo {
- *samp = lo
- }
- }
-}
-
-/// Render writes the min, max and quartiles of the provided `Summary` to the provided `Writer`.
-pub fn write_5_number_summary(w: &mut io::Writer,
- s: &Summary) -> io::IoResult<()> {
- let (q1,q2,q3) = s.quartiles;
- write!(w, "(min={}, q1={}, med={}, q3={}, max={})",
- s.min,
- q1,
- q2,
- q3,
- s.max)
-}
-
-/// Render a boxplot to the provided writer. The boxplot shows the min, max and quartiles of the
-/// provided `Summary` (thus includes the mean) and is scaled to display within the range of the
-/// nearest multiple-of-a-power-of-ten above and below the min and max of possible values, and
-/// target `width_hint` characters of display (though it will be wider if necessary).
-///
-/// As an example, the summary with 5-number-summary `(min=15, q1=17, med=20, q3=24, max=31)` might
-/// display as:
-///
-/// ~~~~ignore
-/// 10 | [--****#******----------] | 40
-/// ~~~~
-
-pub fn write_boxplot(w: &mut io::Writer, s: &Summary,
- width_hint: uint) -> io::IoResult<()> {
-
- let (q1,q2,q3) = s.quartiles;
-
- // the .abs() handles the case where numbers are negative
- let lomag = (10.0_f64).powf(&(s.min.abs().log10().floor()));
- let himag = (10.0_f64).powf(&(s.max.abs().log10().floor()));
-
- // need to consider when the limit is zero
- let lo = if lomag == 0.0 {
- 0.0
- } else {
- (s.min / lomag).floor() * lomag
- };
-
- let hi = if himag == 0.0 {
- 0.0
- } else {
- (s.max / himag).ceil() * himag
- };
-
- let range = hi - lo;
-
- let lostr = lo.to_str();
- let histr = hi.to_str();
-
- let overhead_width = lostr.len() + histr.len() + 4;
- let range_width = width_hint - overhead_width;;
- let char_step = range / (range_width as f64);
-
- try!(write!(w, "{} |", lostr));
-
- let mut c = 0;
- let mut v = lo;
-
- while c < range_width && v < s.min {
- try!(write!(w, " "));
- v += char_step;
- c += 1;
- }
- try!(write!(w, "["));
- c += 1;
- while c < range_width && v < q1 {
- try!(write!(w, "-"));
- v += char_step;
- c += 1;
- }
- while c < range_width && v < q2 {
- try!(write!(w, "*"));
- v += char_step;
- c += 1;
- }
- try!(write!(w, r"\#"));
- c += 1;
- while c < range_width && v < q3 {
- try!(write!(w, "*"));
- v += char_step;
- c += 1;
- }
- while c < range_width && v < s.max {
- try!(write!(w, "-"));
- v += char_step;
- c += 1;
- }
- try!(write!(w, "]"));
- while c < range_width {
- try!(write!(w, " "));
- v += char_step;
- c += 1;
- }
-
- try!(write!(w, "| {}", histr));
- Ok(())
-}
-
-/// Returns a HashMap with the number of occurrences of every element in the
-/// sequence that the iterator exposes.
-pub fn freq_count<T: Iterator<U>, U: Eq+Hash>(mut iter: T) -> hashmap::HashMap<U, uint> {
- let mut map: hashmap::HashMap<U,uint> = hashmap::HashMap::new();
- for elem in iter {
- map.insert_or_update_with(elem, 1, |_, count| *count += 1);
- }
- map
-}
-
-// Test vectors generated from R, using the script src/etc/stat-test-vectors.r.
-
-#[cfg(test)]
-mod tests {
- use stats::Stats;
- use stats::Summary;
- use stats::write_5_number_summary;
- use stats::write_boxplot;
- use std::io;
- use std::str;
- use std::f64;
-
- macro_rules! assert_approx_eq(
- ($a:expr, $b:expr) => ({
- let (a, b) = (&$a, &$b);
- assert!((*a - *b).abs() < 1.0e-6,
- "{} is not approximately equal to {}", *a, *b);
- })
- )
-
- fn check(samples: &[f64], summ: &Summary) {
-
- let summ2 = Summary::new(samples);
-
- let mut w = io::stdout();
- let w = &mut w as &mut io::Writer;
- (write!(w, "\n")).unwrap();
- write_5_number_summary(w, &summ2).unwrap();
- (write!(w, "\n")).unwrap();
- write_boxplot(w, &summ2, 50).unwrap();
- (write!(w, "\n")).unwrap();
-
- assert_eq!(summ.sum, summ2.sum);
- assert_eq!(summ.min, summ2.min);
- assert_eq!(summ.max, summ2.max);
- assert_eq!(summ.mean, summ2.mean);
- assert_eq!(summ.median, summ2.median);
-
- // We needed a few more digits to get exact equality on these
- // but they're within float epsilon, which is 1.0e-6.
- assert_approx_eq!(summ.var, summ2.var);
- assert_approx_eq!(summ.std_dev, summ2.std_dev);
- assert_approx_eq!(summ.std_dev_pct, summ2.std_dev_pct);
- assert_approx_eq!(summ.median_abs_dev, summ2.median_abs_dev);
- assert_approx_eq!(summ.median_abs_dev_pct, summ2.median_abs_dev_pct);
-
- assert_eq!(summ.quartiles, summ2.quartiles);
- assert_eq!(summ.iqr, summ2.iqr);
- }
-
- #[test]
- fn test_min_max_nan() {
- let xs = &[1.0, 2.0, f64::NAN, 3.0, 4.0];
- let summary = Summary::new(xs);
- assert_eq!(summary.min, 1.0);
- assert_eq!(summary.max, 4.0);
- }
-
- #[test]
- fn test_norm2() {
- let val = &[
- 958.0000000000,
- 924.0000000000,
- ];
- let summ = &Summary {
- sum: 1882.0000000000,
- min: 924.0000000000,
- max: 958.0000000000,
- mean: 941.0000000000,
- median: 941.0000000000,
- var: 578.0000000000,
- std_dev: 24.0416305603,
- std_dev_pct: 2.5549022912,
- median_abs_dev: 25.2042000000,
- median_abs_dev_pct: 2.6784484591,
- quartiles: (932.5000000000,941.0000000000,949.5000000000),
- iqr: 17.0000000000,
- };
- check(val, summ);
- }
- #[test]
- fn test_norm10narrow() {
- let val = &[
- 966.0000000000,
- 985.0000000000,
- 1110.0000000000,
- 848.0000000000,
- 821.0000000000,
- 975.0000000000,
- 962.0000000000,
- 1157.0000000000,
- 1217.0000000000,
- 955.0000000000,
- ];
- let summ = &Summary {
- sum: 9996.0000000000,
- min: 821.0000000000,
- max: 1217.0000000000,
- mean: 999.6000000000,
- median: 970.5000000000,
- var: 16050.7111111111,
- std_dev: 126.6914010938,
- std_dev_pct: 12.6742097933,
- median_abs_dev: 102.2994000000,
- median_abs_dev_pct: 10.5408964451,
- quartiles: (956.7500000000,970.5000000000,1078.7500000000),
- iqr: 122.0000000000,
- };
- check(val, summ);
- }
- #[test]
- fn test_norm10medium() {
- let val = &[
- 954.0000000000,
- 1064.0000000000,
- 855.0000000000,
- 1000.0000000000,
- 743.0000000000,
- 1084.0000000000,
- 704.0000000000,
- 1023.0000000000,
- 357.0000000000,
- 869.0000000000,
- ];
- let summ = &Summary {
- sum: 8653.0000000000,
- min: 357.0000000000,
- max: 1084.0000000000,
- mean: 865.3000000000,
- median: 911.5000000000,
- var: 48628.4555555556,
- std_dev: 220.5186059170,
- std_dev_pct: 25.4846418487,
- median_abs_dev: 195.7032000000,
- median_abs_dev_pct: 21.4704552935,
- quartiles: (771.0000000000,911.5000000000,1017.2500000000),
- iqr: 246.2500000000,
- };
- check(val, summ);
- }
- #[test]
- fn test_norm10wide() {
- let val = &[
- 505.0000000000,
- 497.0000000000,
- 1591.0000000000,
- 887.0000000000,
- 1026.0000000000,
- 136.0000000000,
- 1580.0000000000,
- 940.0000000000,
- 754.0000000000,
- 1433.0000000000,
- ];
- let summ = &Summary {
- sum: 9349.0000000000,
- min: 136.0000000000,
- max: 1591.0000000000,
- mean: 934.9000000000,
- median: 913.5000000000,
- var: 239208.9888888889,
- std_dev: 489.0899599142,
- std_dev_pct: 52.3146817750,
- median_abs_dev: 611.5725000000,
- median_abs_dev_pct: 66.9482758621,
- quartiles: (567.2500000000,913.5000000000,1331.2500000000),
- iqr: 764.0000000000,
- };
- check(val, summ);
- }
- #[test]
- fn test_norm25verynarrow() {
- let val = &[
- 991.0000000000,
- 1018.0000000000,
- 998.0000000000,
- 1013.0000000000,
- 974.0000000000,
- 1007.0000000000,
- 1014.0000000000,
- 999.0000000000,
- 1011.0000000000,
- 978.0000000000,
- 985.0000000000,
- 999.0000000000,
- 983.0000000000,
- 982.0000000000,
- 1015.0000000000,
- 1002.0000000000,
- 977.0000000000,
- 948.0000000000,
- 1040.0000000000,
- 974.0000000000,
- 996.0000000000,
- 989.0000000000,
- 1015.0000000000,
- 994.0000000000,
- 1024.0000000000,
- ];
- let summ = &Summary {
- sum: 24926.0000000000,
- min: 948.0000000000,
- max: 1040.0000000000,
- mean: 997.0400000000,
- median: 998.0000000000,
- var: 393.2066666667,
- std_dev: 19.8294393937,
- std_dev_pct: 1.9888308788,
- median_abs_dev: 22.2390000000,
- median_abs_dev_pct: 2.2283567134,
- quartiles: (983.0000000000,998.0000000000,1013.0000000000),
- iqr: 30.0000000000,
- };
- check(val, summ);
- }
- #[test]
- fn test_exp10a() {
- let val = &[
- 23.0000000000,
- 11.0000000000,
- 2.0000000000,
- 57.0000000000,
- 4.0000000000,
- 12.0000000000,
- 5.0000000000,
- 29.0000000000,
- 3.0000000000,
- 21.0000000000,
- ];
- let summ = &Summary {
- sum: 167.0000000000,
- min: 2.0000000000,
- max: 57.0000000000,
- mean: 16.7000000000,
- median: 11.5000000000,
- var: 287.7888888889,
- std_dev: 16.9643416875,
- std_dev_pct: 101.5828843560,
- median_abs_dev: 13.3434000000,
- median_abs_dev_pct: 116.0295652174,
- quartiles: (4.2500000000,11.5000000000,22.5000000000),
- iqr: 18.2500000000,
- };
- check(val, summ);
- }
- #[test]
- fn test_exp10b() {
- let val = &[
- 24.0000000000,
- 17.0000000000,
- 6.0000000000,
- 38.0000000000,
- 25.0000000000,
- 7.0000000000,
- 51.0000000000,
- 2.0000000000,
- 61.0000000000,
- 32.0000000000,
- ];
- let summ = &Summary {
- sum: 263.0000000000,
- min: 2.0000000000,
- max: 61.0000000000,
- mean: 26.3000000000,
- median: 24.5000000000,
- var: 383.5666666667,
- std_dev: 19.5848580967,
- std_dev_pct: 74.4671410520,
- median_abs_dev: 22.9803000000,
- median_abs_dev_pct: 93.7971428571,
- quartiles: (9.5000000000,24.5000000000,36.5000000000),
- iqr: 27.0000000000,
- };
- check(val, summ);
- }
- #[test]
- fn test_exp10c() {
- let val = &[
- 71.0000000000,
- 2.0000000000,
- 32.0000000000,
- 1.0000000000,
- 6.0000000000,
- 28.0000000000,
- 13.0000000000,
- 37.0000000000,
- 16.0000000000,
- 36.0000000000,
- ];
- let summ = &Summary {
- sum: 242.0000000000,
- min: 1.0000000000,
- max: 71.0000000000,
- mean: 24.2000000000,
- median: 22.0000000000,
- var: 458.1777777778,
- std_dev: 21.4050876611,
- std_dev_pct: 88.4507754589,
- median_abs_dev: 21.4977000000,
- median_abs_dev_pct: 97.7168181818,
- quartiles: (7.7500000000,22.0000000000,35.0000000000),
- iqr: 27.2500000000,
- };
- check(val, summ);
- }
- #[test]
- fn test_exp25() {
- let val = &[
- 3.0000000000,
- 24.0000000000,
- 1.0000000000,
- 19.0000000000,
- 7.0000000000,
- 5.0000000000,
- 30.0000000000,
- 39.0000000000,
- 31.0000000000,
- 13.0000000000,
- 25.0000000000,
- 48.0000000000,
- 1.0000000000,
- 6.0000000000,
- 42.0000000000,
- 63.0000000000,
- 2.0000000000,
- 12.0000000000,
- 108.0000000000,
- 26.0000000000,
- 1.0000000000,
- 7.0000000000,
- 44.0000000000,
- 25.0000000000,
- 11.0000000000,
- ];
- let summ = &Summary {
- sum: 593.0000000000,
- min: 1.0000000000,
- max: 108.0000000000,
- mean: 23.7200000000,
- median: 19.0000000000,
- var: 601.0433333333,
- std_dev: 24.5161851301,
- std_dev_pct: 103.3565983562,
- median_abs_dev: 19.2738000000,
- median_abs_dev_pct: 101.4410526316,
- quartiles: (6.0000000000,19.0000000000,31.0000000000),
- iqr: 25.0000000000,
- };
- check(val, summ);
- }
- #[test]
- fn test_binom25() {
- let val = &[
- 18.0000000000,
- 17.0000000000,
- 27.0000000000,
- 15.0000000000,
- 21.0000000000,
- 25.0000000000,
- 17.0000000000,
- 24.0000000000,
- 25.0000000000,
- 24.0000000000,
- 26.0000000000,
- 26.0000000000,
- 23.0000000000,
- 15.0000000000,
- 23.0000000000,
- 17.0000000000,
- 18.0000000000,
- 18.0000000000,
- 21.0000000000,
- 16.0000000000,
- 15.0000000000,
- 31.0000000000,
- 20.0000000000,
- 17.0000000000,
- 15.0000000000,
- ];
- let summ = &Summary {
- sum: 514.0000000000,
- min: 15.0000000000,
- max: 31.0000000000,
- mean: 20.5600000000,
- median: 20.0000000000,
- var: 20.8400000000,
- std_dev: 4.5650848842,
- std_dev_pct: 22.2037202539,
- median_abs_dev: 5.9304000000,
- median_abs_dev_pct: 29.6520000000,
- quartiles: (17.0000000000,20.0000000000,24.0000000000),
- iqr: 7.0000000000,
- };
- check(val, summ);
- }
- #[test]
- fn test_pois25lambda30() {
- let val = &[
- 27.0000000000,
- 33.0000000000,
- 34.0000000000,
- 34.0000000000,
- 24.0000000000,
- 39.0000000000,
- 28.0000000000,
- 27.0000000000,
- 31.0000000000,
- 28.0000000000,
- 38.0000000000,
- 21.0000000000,
- 33.0000000000,
- 36.0000000000,
- 29.0000000000,
- 37.0000000000,
- 32.0000000000,
- 34.0000000000,
- 31.0000000000,
- 39.0000000000,
- 25.0000000000,
- 31.0000000000,
- 32.0000000000,
- 40.0000000000,
- 24.0000000000,
- ];
- let summ = &Summary {
- sum: 787.0000000000,
- min: 21.0000000000,
- max: 40.0000000000,
- mean: 31.4800000000,
- median: 32.0000000000,
- var: 26.5933333333,
- std_dev: 5.1568724372,
- std_dev_pct: 16.3814245145,
- median_abs_dev: 5.9304000000,
- median_abs_dev_pct: 18.5325000000,
- quartiles: (28.0000000000,32.0000000000,34.0000000000),
- iqr: 6.0000000000,
- };
- check(val, summ);
- }
- #[test]
- fn test_pois25lambda40() {
- let val = &[
- 42.0000000000,
- 50.0000000000,
- 42.0000000000,
- 46.0000000000,
- 34.0000000000,
- 45.0000000000,
- 34.0000000000,
- 49.0000000000,
- 39.0000000000,
- 28.0000000000,
- 40.0000000000,
- 35.0000000000,
- 37.0000000000,
- 39.0000000000,
- 46.0000000000,
- 44.0000000000,
- 32.0000000000,
- 45.0000000000,
- 42.0000000000,
- 37.0000000000,
- 48.0000000000,
- 42.0000000000,
- 33.0000000000,
- 42.0000000000,
- 48.0000000000,
- ];
- let summ = &Summary {
- sum: 1019.0000000000,
- min: 28.0000000000,
- max: 50.0000000000,
- mean: 40.7600000000,
- median: 42.0000000000,
- var: 34.4400000000,
- std_dev: 5.8685603004,
- std_dev_pct: 14.3978417577,
- median_abs_dev: 5.9304000000,
- median_abs_dev_pct: 14.1200000000,
- quartiles: (37.0000000000,42.0000000000,45.0000000000),
- iqr: 8.0000000000,
- };
- check(val, summ);
- }
- #[test]
- fn test_pois25lambda50() {
- let val = &[
- 45.0000000000,
- 43.0000000000,
- 44.0000000000,
- 61.0000000000,
- 51.0000000000,
- 53.0000000000,
- 59.0000000000,
- 52.0000000000,
- 49.0000000000,
- 51.0000000000,
- 51.0000000000,
- 50.0000000000,
- 49.0000000000,
- 56.0000000000,
- 42.0000000000,
- 52.0000000000,
- 51.0000000000,
- 43.0000000000,
- 48.0000000000,
- 48.0000000000,
- 50.0000000000,
- 42.0000000000,
- 43.0000000000,
- 42.0000000000,
- 60.0000000000,
- ];
- let summ = &Summary {
- sum: 1235.0000000000,
- min: 42.0000000000,
- max: 61.0000000000,
- mean: 49.4000000000,
- median: 50.0000000000,
- var: 31.6666666667,
- std_dev: 5.6273143387,
- std_dev_pct: 11.3913245723,
- median_abs_dev: 4.4478000000,
- median_abs_dev_pct: 8.8956000000,
- quartiles: (44.0000000000,50.0000000000,52.0000000000),
- iqr: 8.0000000000,
- };
- check(val, summ);
- }
- #[test]
- fn test_unif25() {
- let val = &[
- 99.0000000000,
- 55.0000000000,
- 92.0000000000,
- 79.0000000000,
- 14.0000000000,
- 2.0000000000,
- 33.0000000000,
- 49.0000000000,
- 3.0000000000,
- 32.0000000000,
- 84.0000000000,
- 59.0000000000,
- 22.0000000000,
- 86.0000000000,
- 76.0000000000,
- 31.0000000000,
- 29.0000000000,
- 11.0000000000,
- 41.0000000000,
- 53.0000000000,
- 45.0000000000,
- 44.0000000000,
- 98.0000000000,
- 98.0000000000,
- 7.0000000000,
- ];
- let summ = &Summary {
- sum: 1242.0000000000,
- min: 2.0000000000,
- max: 99.0000000000,
- mean: 49.6800000000,
- median: 45.0000000000,
- var: 1015.6433333333,
- std_dev: 31.8691595957,
- std_dev_pct: 64.1488719719,
- median_abs_dev: 45.9606000000,
- median_abs_dev_pct: 102.1346666667,
- quartiles: (29.0000000000,45.0000000000,79.0000000000),
- iqr: 50.0000000000,
- };
- check(val, summ);
- }
-
- #[test]
- fn test_boxplot_nonpositive() {
- fn t(s: &Summary, expected: ~str) {
- use std::io::MemWriter;
- let mut m = MemWriter::new();
- write_boxplot(&mut m as &mut io::Writer, s, 30).unwrap();
- let out = str::from_utf8_owned(m.unwrap()).unwrap();
- assert_eq!(out, expected);
- }
-
- t(&Summary::new([-2.0, -1.0]), ~"-2 |[------******#*****---]| -1");
- t(&Summary::new([0.0, 2.0]), ~"0 |[-------*****#*******---]| 2");
- t(&Summary::new([-2.0, 0.0]), ~"-2 |[------******#******---]| 0");
-
- }
- #[test]
- fn test_sum_f64s() {
- assert_eq!([0.5, 3.2321, 1.5678].sum(), 5.2999);
- }
- #[test]
- fn test_sum_f64_between_ints_that_sum_to_0() {
- assert_eq!([1e30, 1.2, -1e30].sum(), 1.2);
- }
-}
-
-#[cfg(test)]
-mod bench {
- extern crate test;
- use self::test::BenchHarness;
- use std::vec;
- use stats::Stats;
-
- #[bench]
- fn sum_three_items(bh: &mut BenchHarness) {
- bh.iter(|| {
- [1e20, 1.5, -1e20].sum();
- })
- }
- #[bench]
- fn sum_many_f64(bh: &mut BenchHarness) {
- let nums = [-1e30, 1e60, 1e30, 1.0, -1e60];
- let v = vec::from_fn(500, |i| nums[i%5]);
-
- bh.iter(|| {
- v.sum();
- })
- }
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Temporary files and directories
-
-
-use std::os;
-use rand::{task_rng, Rng};
-use std::io;
-use std::io::fs;
-
-/// A wrapper for a path to temporary directory implementing automatic
-/// scope-based deletion.
-pub struct TempDir {
- priv path: Option<Path>
-}
-
-impl TempDir {
- /// Attempts to make a temporary directory inside of `tmpdir` whose name
- /// will have the suffix `suffix`. The directory will be automatically
- /// deleted once the returned wrapper is destroyed.
- ///
- /// If no directory can be created, None is returned.
- pub fn new_in(tmpdir: &Path, suffix: &str) -> Option<TempDir> {
- if !tmpdir.is_absolute() {
- let abs_tmpdir = os::make_absolute(tmpdir);
- return TempDir::new_in(&abs_tmpdir, suffix);
- }
-
- let mut r = task_rng();
- for _ in range(0u, 1000) {
- let p = tmpdir.join(r.gen_ascii_str(16) + suffix);
- match fs::mkdir(&p, io::UserRWX) {
- Err(..) => {}
- Ok(()) => return Some(TempDir { path: Some(p) })
- }
- }
- None
- }
-
- /// Attempts to make a temporary directory inside of `os::tmpdir()` whose
- /// name will have the suffix `suffix`. The directory will be automatically
- /// deleted once the returned wrapper is destroyed.
- ///
- /// If no directory can be created, None is returned.
- pub fn new(suffix: &str) -> Option<TempDir> {
- TempDir::new_in(&os::tmpdir(), suffix)
- }
-
- /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper.
- /// This discards the wrapper so that the automatic deletion of the
- /// temporary directory is prevented.
- pub fn unwrap(self) -> Path {
- let mut tmpdir = self;
- tmpdir.path.take_unwrap()
- }
-
- /// Access the wrapped `std::path::Path` to the temporary directory.
- pub fn path<'a>(&'a self) -> &'a Path {
- self.path.get_ref()
- }
-}
-
-impl Drop for TempDir {
- fn drop(&mut self) {
- for path in self.path.iter() {
- if path.exists() {
- // FIXME: is failing the right thing to do?
- fs::rmdir_recursive(path).unwrap();
- }
- }
- }
-}
-
-// the tests for this module need to change the path using change_dir,
-// and this doesn't play nicely with other tests so these unit tests are located
-// in src/test/run-pass/tempfile.rs
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[allow(missing_doc)];
-
-pub mod icu {
- pub type UBool = u8;
- pub type UProperty = int;
- pub type UChar32 = char;
-
- pub static TRUE : u8 = 1u8;
- pub static FALSE : u8 = 0u8;
-
- pub static UCHAR_ALPHABETIC : UProperty = 0;
- pub static UCHAR_BINARY_START : UProperty = 0; // = UCHAR_ALPHABETIC
- pub static UCHAR_ASCII_HEX_DIGIT : UProperty = 1;
- pub static UCHAR_BIDI_CONTROL : UProperty = 2;
-
- pub static UCHAR_BIDI_MIRRORED : UProperty = 3;
- pub static UCHAR_DASH : UProperty = 4;
- pub static UCHAR_DEFAULT_IGNORABLE_CODE_POINT : UProperty = 5;
- pub static UCHAR_DEPRECATED : UProperty = 6;
-
- pub static UCHAR_DIACRITIC : UProperty = 7;
- pub static UCHAR_EXTENDER : UProperty = 8;
- pub static UCHAR_FULL_COMPOSITION_EXCLUSION : UProperty = 9;
- pub static UCHAR_GRAPHEME_BASE : UProperty = 10;
-
- pub static UCHAR_GRAPHEME_EXTEND : UProperty = 11;
- pub static UCHAR_GRAPHEME_LINK : UProperty = 12;
- pub static UCHAR_HEX_DIGIT : UProperty = 13;
- pub static UCHAR_HYPHEN : UProperty = 14;
-
- pub static UCHAR_ID_CONTINUE : UProperty = 15;
- pub static UCHAR_ID_START : UProperty = 16;
- pub static UCHAR_IDEOGRAPHIC : UProperty = 17;
- pub static UCHAR_IDS_BINARY_OPERATOR : UProperty = 18;
-
- pub static UCHAR_IDS_TRINARY_OPERATOR : UProperty = 19;
- pub static UCHAR_JOIN_CONTROL : UProperty = 20;
- pub static UCHAR_LOGICAL_ORDER_EXCEPTION : UProperty = 21;
- pub static UCHAR_LOWERCASE : UProperty = 22;
-
- pub static UCHAR_MATH : UProperty = 23;
- pub static UCHAR_NONCHARACTER_CODE_POINT : UProperty = 24;
- pub static UCHAR_QUOTATION_MARK : UProperty = 25;
- pub static UCHAR_RADICAL : UProperty = 26;
-
- pub static UCHAR_SOFT_DOTTED : UProperty = 27;
- pub static UCHAR_TERMINAL_PUNCTUATION : UProperty = 28;
- pub static UCHAR_UNIFIED_IDEOGRAPH : UProperty = 29;
- pub static UCHAR_UPPERCASE : UProperty = 30;
-
- pub static UCHAR_WHITE_SPACE : UProperty = 31;
- pub static UCHAR_XID_CONTINUE : UProperty = 32;
- pub static UCHAR_XID_START : UProperty = 33;
- pub static UCHAR_CASE_SENSITIVE : UProperty = 34;
-
- pub static UCHAR_S_TERM : UProperty = 35;
- pub static UCHAR_VARIATION_SELECTOR : UProperty = 36;
- pub static UCHAR_NFD_INERT : UProperty = 37;
- pub static UCHAR_NFKD_INERT : UProperty = 38;
-
- pub static UCHAR_NFC_INERT : UProperty = 39;
- pub static UCHAR_NFKC_INERT : UProperty = 40;
- pub static UCHAR_SEGMENT_STARTER : UProperty = 41;
- pub static UCHAR_PATTERN_SYNTAX : UProperty = 42;
-
- pub static UCHAR_PATTERN_WHITE_SPACE : UProperty = 43;
- pub static UCHAR_POSIX_ALNUM : UProperty = 44;
- pub static UCHAR_POSIX_BLANK : UProperty = 45;
- pub static UCHAR_POSIX_GRAPH : UProperty = 46;
-
- pub static UCHAR_POSIX_PRINT : UProperty = 47;
- pub static UCHAR_POSIX_XDIGIT : UProperty = 48;
- pub static UCHAR_CASED : UProperty = 49;
- pub static UCHAR_CASE_IGNORABLE : UProperty = 50;
-
- pub static UCHAR_CHANGES_WHEN_LOWERCASED : UProperty = 51;
- pub static UCHAR_CHANGES_WHEN_UPPERCASED : UProperty = 52;
- pub static UCHAR_CHANGES_WHEN_TITLECASED : UProperty = 53;
- pub static UCHAR_CHANGES_WHEN_CASEFOLDED : UProperty = 54;
-
- pub static UCHAR_CHANGES_WHEN_CASEMAPPED : UProperty = 55;
- pub static UCHAR_CHANGES_WHEN_NFKC_CASEFOLDED : UProperty = 56;
- pub static UCHAR_BINARY_LIMIT : UProperty = 57;
- pub static UCHAR_BIDI_CLASS : UProperty = 0x1000;
-
- pub static UCHAR_INT_START : UProperty = 0x1000; // UCHAR_BIDI_CLASS
- pub static UCHAR_BLOCK : UProperty = 0x1001;
- pub static UCHAR_CANONICAL_COMBINING_CLASS : UProperty = 0x1002;
- pub static UCHAR_DECOMPOSITION_TYPE : UProperty = 0x1003;
-
- pub static UCHAR_EAST_ASIAN_WIDTH : UProperty = 0x1004;
- pub static UCHAR_GENERAL_CATEGORY : UProperty = 0x1005;
- pub static UCHAR_JOINING_GROUP : UProperty = 0x1006;
- pub static UCHAR_JOINING_TYPE : UProperty = 0x1007;
-
- pub static UCHAR_LINE_BREAK : UProperty = 0x1008;
- pub static UCHAR_NUMERIC_TYPE : UProperty = 0x1009;
- pub static UCHAR_SCRIPT : UProperty = 0x100A;
- pub static UCHAR_HANGUL_SYLLABLE_TYPE : UProperty = 0x100B;
-
- pub static UCHAR_NFD_QUICK_CHECK : UProperty = 0x100C;
- pub static UCHAR_NFKD_QUICK_CHECK : UProperty = 0x100D;
- pub static UCHAR_NFC_QUICK_CHECK : UProperty = 0x100E;
- pub static UCHAR_NFKC_QUICK_CHECK : UProperty = 0x100F;
-
- pub static UCHAR_LEAD_CANONICAL_COMBINING_CLASS : UProperty = 0x1010;
- pub static UCHAR_TRAIL_CANONICAL_COMBINING_CLASS : UProperty = 0x1011;
- pub static UCHAR_GRAPHEME_CLUSTER_BREAK : UProperty = 0x1012;
- pub static UCHAR_SENTENCE_BREAK : UProperty = 0x1013;
-
- pub static UCHAR_WORD_BREAK : UProperty = 0x1014;
- pub static UCHAR_INT_LIMIT : UProperty = 0x1015;
-
- pub static UCHAR_GENERAL_CATEGORY_MASK : UProperty = 0x2000;
- pub static UCHAR_MASK_START : UProperty = 0x2000;
- // = UCHAR_GENERAL_CATEGORY_MASK
- pub static UCHAR_MASK_LIMIT : UProperty = 0x2001;
-
- pub static UCHAR_NUMERIC_VALUE : UProperty = 0x3000;
- pub static UCHAR_DOUBLE_START : UProperty = 0x3000;
- // = UCHAR_NUMERIC_VALUE
- pub static UCHAR_DOUBLE_LIMIT : UProperty = 0x3001;
-
- pub static UCHAR_AGE : UProperty = 0x4000;
- pub static UCHAR_STRING_START : UProperty = 0x4000; // = UCHAR_AGE
- pub static UCHAR_BIDI_MIRRORING_GLYPH : UProperty = 0x4001;
- pub static UCHAR_CASE_FOLDING : UProperty = 0x4002;
-
- pub static UCHAR_ISO_COMMENT : UProperty = 0x4003;
- pub static UCHAR_LOWERCASE_MAPPING : UProperty = 0x4004;
- pub static UCHAR_NAME : UProperty = 0x4005;
- pub static UCHAR_SIMPLE_CASE_FOLDING : UProperty = 0x4006;
-
- pub static UCHAR_SIMPLE_LOWERCASE_MAPPING : UProperty = 0x4007;
- pub static UCHAR_SIMPLE_TITLECASE_MAPPING : UProperty = 0x4008;
- pub static UCHAR_SIMPLE_UPPERCASE_MAPPING : UProperty = 0x4009;
- pub static UCHAR_TITLECASE_MAPPING : UProperty = 0x400A;
-
- pub static UCHAR_UNICODE_1_NAME : UProperty = 0x400B;
- pub static UCHAR_UPPERCASE_MAPPING : UProperty = 0x400C;
- pub static UCHAR_STRING_LIMIT : UProperty = 0x400D;
-
- pub static UCHAR_SCRIPT_EXTENSIONS : UProperty = 0x7000;
- pub static UCHAR_OTHER_PROPERTY_START : UProperty = 0x7000;
- // = UCHAR_SCRIPT_EXTENSIONS;
- pub static UCHAR_OTHER_PROPERTY_LIMIT : UProperty = 0x7001;
-
- pub static UCHAR_INVALID_CODE : UProperty = -1;
-
- pub mod libicu {
- use unicode::icu::*;
-
- // #[link_name = "icuuc"]
- #[link(name = "icuuc")]
- extern {
- pub fn u_hasBinaryProperty(c: UChar32, which: UProperty) -> UBool;
- pub fn u_isdigit(c: UChar32) -> UBool;
- pub fn u_islower(c: UChar32) -> UBool;
- pub fn u_isspace(c: UChar32) -> UBool;
- pub fn u_isupper(c: UChar32) -> UBool;
- pub fn u_tolower(c: UChar32) -> UChar32;
- pub fn u_toupper(c: UChar32) -> UChar32;
- }
- }
-}
-
-pub fn is_XID_start(c: char) -> bool {
- unsafe {
- return icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START)
- == icu::TRUE;
- }
-}
-
-pub fn is_XID_continue(c: char) -> bool {
- unsafe {
- return icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START)
- == icu::TRUE;
- }
-}
-
-/*
-Function: is_digit
-
-Returns true if a character is a digit.
-*/
-pub fn is_digit(c: char) -> bool {
- unsafe {
- return icu::libicu::u_isdigit(c) == icu::TRUE;
- }
-}
-
-/*
-Function: is_lower
-
-Returns true if a character is a lowercase letter.
-*/
-pub fn is_lower(c: char) -> bool {
- unsafe {
- return icu::libicu::u_islower(c) == icu::TRUE;
- }
-}
-
-/*
-Function: is_space
-
-Returns true if a character is space.
-*/
-pub fn is_space(c: char) -> bool {
- unsafe {
- return icu::libicu::u_isspace(c) == icu::TRUE;
- }
-}
-
-/*
-Function: is_upper
-
-Returns true if a character is an uppercase letter.
-*/
-pub fn is_upper(c: char) -> bool {
- unsafe {
- return icu::libicu::u_isupper(c) == icu::TRUE;
- }
-}
-
-#[cfg(test)]
-mod tests {
- use unicode::*;
-
- #[test]
- fn test_is_digit() {
- assert!((is_digit('0')));
- assert!((!is_digit('m')));
- }
-
- #[test]
- fn test_is_lower() {
- assert!((is_lower('m')));
- assert!((!is_lower('M')));
- }
-
- #[test]
- fn test_is_space() {
- assert!((is_space(' ')));
- assert!((!is_space('m')));
- }
-
- #[test]
- fn test_is_upper() {
- assert!((is_upper('M')));
- assert!((!is_upper('m')));
- }
-}
+++ /dev/null
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Types/fns concerning URLs (see RFC 3986)
-
-#[allow(missing_doc)];
-
-use std::cmp::Eq;
-use std::fmt;
-use std::hash::Hash;
-use std::io::BufReader;
-use std::from_str::FromStr;
-use std::uint;
-
-use collections::HashMap;
-
-/// A Uniform Resource Locator (URL). A URL is a form of URI (Uniform Resource
-/// Identifier) that includes network location information, such as hostname or
-/// port number.
-///
-/// # Example
-///
-/// ```rust
-/// use extra::url::{Url, UserInfo};
-///
-/// let url = Url { scheme: ~"https",
-/// user: Some(UserInfo { user: ~"username", pass: None }),
-/// host: ~"example.com",
-/// port: Some(~"8080"),
-/// path: ~"/foo/bar",
-/// query: ~[(~"baz", ~"qux")],
-/// fragment: Some(~"quz") };
-/// // https://username@example.com:8080/foo/bar?baz=qux#quz
-/// ```
-#[deriving(Clone, Eq)]
-pub struct Url {
- /// The scheme part of a URL, such as `https` in the above example.
- scheme: ~str,
- /// A URL subcomponent for user authentication. `username` in the above example.
- user: Option<UserInfo>,
- /// A domain name or IP address. For example, `example.com`.
- host: ~str,
- /// A TCP port number, for example `8080`.
- port: Option<~str>,
- /// The path component of a URL, for example `/foo/bar`.
- path: ~str,
- /// The query component of a URL. `~[(~"baz", ~"qux")]` represents the
- /// fragment `baz=qux` in the above example.
- query: Query,
- /// The fragment component, such as `quz`. Doesn't include the leading `#` character.
- fragment: Option<~str>
-}
-
-#[deriving(Clone, Eq)]
-pub struct Path {
- /// The path component of a URL, for example `/foo/bar`.
- path: ~str,
- /// The query component of a URL. `~[(~"baz", ~"qux")]` represents the
- /// fragment `baz=qux` in the above example.
- query: Query,
- /// The fragment component, such as `quz`. Doesn't include the leading `#` character.
- fragment: Option<~str>
-}
-
-/// An optional subcomponent of a URI authority component.
-#[deriving(Clone, Eq)]
-pub struct UserInfo {
- /// The user name.
- user: ~str,
- /// Password or other scheme-specific authentication information.
- pass: Option<~str>
-}
-
-/// Represents the query component of a URI.
-pub type Query = ~[(~str, ~str)];
-
-impl Url {
- pub fn new(scheme: ~str,
- user: Option<UserInfo>,
- host: ~str,
- port: Option<~str>,
- path: ~str,
- query: Query,
- fragment: Option<~str>)
- -> Url {
- Url {
- scheme: scheme,
- user: user,
- host: host,
- port: port,
- path: path,
- query: query,
- fragment: fragment,
- }
- }
-}
-
-impl Path {
- pub fn new(path: ~str,
- query: Query,
- fragment: Option<~str>)
- -> Path {
- Path {
- path: path,
- query: query,
- fragment: fragment,
- }
- }
-}
-
-impl UserInfo {
- #[inline]
- pub fn new(user: ~str, pass: Option<~str>) -> UserInfo {
- UserInfo { user: user, pass: pass }
- }
-}
-
-fn encode_inner(s: &str, full_url: bool) -> ~str {
- let mut rdr = BufReader::new(s.as_bytes());
- let mut out = ~"";
-
- loop {
- let mut buf = [0];
- let ch = match rdr.read(buf) {
- Err(..) => break,
- Ok(..) => buf[0] as char,
- };
-
- match ch {
- // unreserved:
- 'A' .. 'Z' |
- 'a' .. 'z' |
- '0' .. '9' |
- '-' | '.' | '_' | '~' => {
- out.push_char(ch);
- }
- _ => {
- if full_url {
- match ch {
- // gen-delims:
- ':' | '/' | '?' | '#' | '[' | ']' | '@' |
-
- // sub-delims:
- '!' | '$' | '&' | '"' | '(' | ')' | '*' |
- '+' | ',' | ';' | '=' => {
- out.push_char(ch);
- }
-
- _ => out.push_str(format!("%{:X}", ch as uint))
- }
- } else {
- out.push_str(format!("%{:X}", ch as uint));
- }
- }
- }
- }
-
- out
-}
-
-/**
- * Encodes a URI by replacing reserved characters with percent-encoded
- * character sequences.
- *
- * This function is compliant with RFC 3986.
- *
- * # Example
- *
- * ```rust
- * use extra::url::encode;
- *
- * let url = encode(&"https://example.com/Rust (programming language)");
- * println!("{}", url); // https://example.com/Rust%20(programming%20language)
- * ```
- */
-pub fn encode(s: &str) -> ~str {
- encode_inner(s, true)
-}
-
-/**
- * Encodes a URI component by replacing reserved characters with percent
- * encoded character sequences.
- *
- * This function is compliant with RFC 3986.
- */
-
-pub fn encode_component(s: &str) -> ~str {
- encode_inner(s, false)
-}
-
-fn decode_inner(s: &str, full_url: bool) -> ~str {
- let mut rdr = BufReader::new(s.as_bytes());
- let mut out = ~"";
-
- loop {
- let mut buf = [0];
- let ch = match rdr.read(buf) {
- Err(..) => break,
- Ok(..) => buf[0] as char
- };
- match ch {
- '%' => {
- let mut bytes = [0, 0];
- match rdr.read(bytes) {
- Ok(2) => {}
- _ => fail!() // FIXME: malformed url?
- }
- let ch = uint::parse_bytes(bytes, 16u).unwrap() as u8 as char;
-
- if full_url {
- // Only decode some characters:
- match ch {
- // gen-delims:
- ':' | '/' | '?' | '#' | '[' | ']' | '@' |
-
- // sub-delims:
- '!' | '$' | '&' | '"' | '(' | ')' | '*' |
- '+' | ',' | ';' | '=' => {
- out.push_char('%');
- out.push_char(bytes[0u] as char);
- out.push_char(bytes[1u] as char);
- }
-
- ch => out.push_char(ch)
- }
- } else {
- out.push_char(ch);
- }
- }
- ch => out.push_char(ch)
- }
- }
-
- out
-}
-
-/**
- * Decodes a percent-encoded string representing a URI.
- *
- * This will only decode escape sequences generated by `encode`.
- *
- * # Example
- *
- * ```rust
- * use extra::url::decode;
- *
- * let url = decode(&"https://example.com/Rust%20(programming%20language)");
- * println!("{}", url); // https://example.com/Rust (programming language)
- * ```
- */
-pub fn decode(s: &str) -> ~str {
- decode_inner(s, true)
-}
-
-/**
- * Decode a string encoded with percent encoding.
- */
-pub fn decode_component(s: &str) -> ~str {
- decode_inner(s, false)
-}
-
-fn encode_plus(s: &str) -> ~str {
- let mut rdr = BufReader::new(s.as_bytes());
- let mut out = ~"";
-
- loop {
- let mut buf = [0];
- let ch = match rdr.read(buf) {
- Ok(..) => buf[0] as char,
- Err(..) => break,
- };
- match ch {
- 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_' | '.' | '-' => {
- out.push_char(ch);
- }
- ' ' => out.push_char('+'),
- _ => out.push_str(format!("%{:X}", ch as uint))
- }
- }
-
- out
-}
-
-/**
- * Encode a hashmap to the 'application/x-www-form-urlencoded' media type.
- */
-pub fn encode_form_urlencoded(m: &HashMap<~str, ~[~str]>) -> ~str {
- let mut out = ~"";
- let mut first = true;
-
- for (key, values) in m.iter() {
- let key = encode_plus(*key);
-
- for value in values.iter() {
- if first {
- first = false;
- } else {
- out.push_char('&');
- first = false;
- }
-
- out.push_str(format!("{}={}", key, encode_plus(*value)));
- }
- }
-
- out
-}
-
-/**
- * Decode a string encoded with the 'application/x-www-form-urlencoded' media
- * type into a hashmap.
- */
-pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, ~[~str]> {
- let mut rdr = BufReader::new(s);
- let mut m = HashMap::new();
- let mut key = ~"";
- let mut value = ~"";
- let mut parsing_key = true;
-
- loop {
- let mut buf = [0];
- let ch = match rdr.read(buf) {
- Ok(..) => buf[0] as char,
- Err(..) => break,
- };
- match ch {
- '&' | ';' => {
- if key != ~"" && value != ~"" {
- let mut values = match m.pop(&key) {
- Some(values) => values,
- None => ~[],
- };
-
- values.push(value);
- m.insert(key, values);
- }
-
- parsing_key = true;
- key = ~"";
- value = ~"";
- }
- '=' => parsing_key = false,
- ch => {
- let ch = match ch {
- '%' => {
- let mut bytes = [0, 0];
- match rdr.read(bytes) {
- Ok(2) => {}
- _ => fail!() // FIXME: malformed?
- }
- uint::parse_bytes(bytes, 16u).unwrap() as u8 as char
- }
- '+' => ' ',
- ch => ch
- };
-
- if parsing_key {
- key.push_char(ch)
- } else {
- value.push_char(ch)
- }
- }
- }
- }
-
- if key != ~"" && value != ~"" {
- let mut values = match m.pop(&key) {
- Some(values) => values,
- None => ~[],
- };
-
- values.push(value);
- m.insert(key, values);
- }
-
- m
-}
-
-
-fn split_char_first(s: &str, c: char) -> (~str, ~str) {
- let len = s.len();
- let mut index = len;
- let mut mat = 0;
- let mut rdr = BufReader::new(s.as_bytes());
- loop {
- let mut buf = [0];
- let ch = match rdr.read(buf) {
- Ok(..) => buf[0] as char,
- Err(..) => break,
- };
- if ch == c {
- // found a match, adjust markers
- index = (rdr.tell().unwrap() as uint) - 1;
- mat = 1;
- break;
- }
- }
- if index+mat == len {
- return (s.slice(0, index).to_owned(), ~"");
- } else {
- return (s.slice(0, index).to_owned(),
- s.slice(index + mat, s.len()).to_owned());
- }
-}
-
-impl fmt::Show for UserInfo {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self.pass {
- Some(ref pass) => write!(f.buf, "{}:{}@", self.user, *pass),
- None => write!(f.buf, "{}@", self.user),
- }
- }
-}
-
-fn query_from_str(rawquery: &str) -> Query {
- let mut query: Query = ~[];
- if !rawquery.is_empty() {
- for p in rawquery.split('&') {
- let (k, v) = split_char_first(p, '=');
- query.push((decode_component(k), decode_component(v)));
- };
- }
- return query;
-}
-
-/**
- * Converts an instance of a URI `Query` type to a string.
- *
- * # Example
- *
- * ```rust
- * use extra::url;
- *
- * let query = ~[(~"title", ~"The Village"), (~"north", ~"52.91"), (~"west", ~"4.10")];
- * println!("{}", url::query_to_str(&query)); // title=The%20Village&north=52.91&west=4.10
- * ```
- */
-#[allow(unused_must_use)]
-pub fn query_to_str(query: &Query) -> ~str {
- use std::io::MemWriter;
- use std::str;
-
- let mut writer = MemWriter::new();
- for (i, &(ref k, ref v)) in query.iter().enumerate() {
- if i != 0 { write!(&mut writer, "&"); }
- write!(&mut writer, "{}={}", encode_component(*k),
- encode_component(*v));
- }
- str::from_utf8_lossy(writer.unwrap()).into_owned()
-}
-
-/**
- * Returns a tuple of the URI scheme and the rest of the URI, or a parsing error.
- *
- * Does not include the separating `:` character.
- *
- * # Example
- *
- * ```rust
- * use extra::url::get_scheme;
- *
- * let scheme = match get_scheme("https://example.com/") {
- * Ok((sch, _)) => sch,
- * Err(_) => ~"(None)",
- * };
- * println!("Scheme in use: {}.", scheme); // Scheme in use: https.
- * ```
- */
-pub fn get_scheme(rawurl: &str) -> Result<(~str, ~str), ~str> {
- for (i,c) in rawurl.chars().enumerate() {
- match c {
- 'A' .. 'Z' | 'a' .. 'z' => continue,
- '0' .. '9' | '+' | '-' | '.' => {
- if i == 0 {
- return Err(~"url: Scheme must begin with a letter.");
- }
- continue;
- }
- ':' => {
- if i == 0 {
- return Err(~"url: Scheme cannot be empty.");
- } else {
- return Ok((rawurl.slice(0,i).to_owned(),
- rawurl.slice(i+1,rawurl.len()).to_owned()));
- }
- }
- _ => {
- return Err(~"url: Invalid character in scheme.");
- }
- }
- };
- return Err(~"url: Scheme must be terminated with a colon.");
-}
-
-#[deriving(Clone, Eq)]
-enum Input {
- Digit, // all digits
- Hex, // digits and letters a-f
- Unreserved // all other legal characters
-}
-
-// returns userinfo, host, port, and unparsed part, or an error
-fn get_authority(rawurl: &str) ->
- Result<(Option<UserInfo>, ~str, Option<~str>, ~str), ~str> {
- if !rawurl.starts_with("//") {
- // there is no authority.
- return Ok((None, ~"", None, rawurl.to_str()));
- }
-
- enum State {
- Start, // starting state
- PassHostPort, // could be in user or port
- Ip6Port, // either in ipv6 host or port
- Ip6Host, // are in an ipv6 host
- InHost, // are in a host - may be ipv6, but don't know yet
- InPort // are in port
- }
-
- let len = rawurl.len();
- let mut st = Start;
- let mut input = Digit; // most restricted, start here.
-
- let mut userinfo = None;
- let mut host = ~"";
- let mut port = None;
-
- let mut colon_count = 0;
- let mut pos = 0;
- let mut begin = 2;
- let mut end = len;
-
- for (i,c) in rawurl.chars().enumerate() {
- if i < 2 { continue; } // ignore the leading //
-
- // deal with input class first
- match c {
- '0' .. '9' => (),
- 'A' .. 'F' | 'a' .. 'f' => {
- if input == Digit {
- input = Hex;
- }
- }
- 'G' .. 'Z' | 'g' .. 'z' | '-' | '.' | '_' | '~' | '%' |
- '&' |'\'' | '(' | ')' | '+' | '!' | '*' | ',' | ';' | '=' => {
- input = Unreserved;
- }
- ':' | '@' | '?' | '#' | '/' => {
- // separators, don't change anything
- }
- _ => {
- return Err(~"Illegal character in authority");
- }
- }
-
- // now process states
- match c {
- ':' => {
- colon_count += 1;
- match st {
- Start => {
- pos = i;
- st = PassHostPort;
- }
- PassHostPort => {
- // multiple colons means ipv6 address.
- if input == Unreserved {
- return Err(
- ~"Illegal characters in IPv6 address.");
- }
- st = Ip6Host;
- }
- InHost => {
- pos = i;
- if input == Unreserved {
- // must be port
- host = rawurl.slice(begin, i).to_owned();
- st = InPort;
- } else {
- // can't be sure whether this is an ipv6 address or a port
- st = Ip6Port;
- }
- }
- Ip6Port => {
- if input == Unreserved {
- return Err(~"Illegal characters in authority.");
- }
- st = Ip6Host;
- }
- Ip6Host => {
- if colon_count > 7 {
- host = rawurl.slice(begin, i).to_owned();
- pos = i;
- st = InPort;
- }
- }
- _ => {
- return Err(~"Invalid ':' in authority.");
- }
- }
- input = Digit; // reset input class
- }
-
- '@' => {
- input = Digit; // reset input class
- colon_count = 0; // reset count
- match st {
- Start => {
- let user = rawurl.slice(begin, i).to_owned();
- userinfo = Some(UserInfo::new(user, None));
- st = InHost;
- }
- PassHostPort => {
- let user = rawurl.slice(begin, pos).to_owned();
- let pass = rawurl.slice(pos+1, i).to_owned();
- userinfo = Some(UserInfo::new(user, Some(pass)));
- st = InHost;
- }
- _ => {
- return Err(~"Invalid '@' in authority.");
- }
- }
- begin = i+1;
- }
-
- '?' | '#' | '/' => {
- end = i;
- break;
- }
- _ => ()
- }
- }
-
- // finish up
- match st {
- Start => {
- host = rawurl.slice(begin, end).to_owned();
- }
- PassHostPort | Ip6Port => {
- if input != Digit {
- return Err(~"Non-digit characters in port.");
- }
- host = rawurl.slice(begin, pos).to_owned();
- port = Some(rawurl.slice(pos+1, end).to_owned());
- }
- Ip6Host | InHost => {
- host = rawurl.slice(begin, end).to_owned();
- }
- InPort => {
- if input != Digit {
- return Err(~"Non-digit characters in port.");
- }
- port = Some(rawurl.slice(pos+1, end).to_owned());
- }
- }
-
- let rest = rawurl.slice(end, len).to_owned();
- return Ok((userinfo, host, port, rest));
-}
-
-
-// returns the path and unparsed part of url, or an error
-fn get_path(rawurl: &str, authority: bool) ->
- Result<(~str, ~str), ~str> {
- let len = rawurl.len();
- let mut end = len;
- for (i,c) in rawurl.chars().enumerate() {
- match c {
- 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '&' |'\'' | '(' | ')' | '.'
- | '@' | ':' | '%' | '/' | '+' | '!' | '*' | ',' | ';' | '='
- | '_' | '-' | '~' => {
- continue;
- }
- '?' | '#' => {
- end = i;
- break;
- }
- _ => return Err(~"Invalid character in path.")
- }
- }
-
- if authority {
- if end != 0 && !rawurl.starts_with("/") {
- return Err(~"Non-empty path must begin with\
- '/' in presence of authority.");
- }
- }
-
- return Ok((decode_component(rawurl.slice(0, end)),
- rawurl.slice(end, len).to_owned()));
-}
-
-// returns the parsed query and the fragment, if present
-fn get_query_fragment(rawurl: &str) ->
- Result<(Query, Option<~str>), ~str> {
- if !rawurl.starts_with("?") {
- if rawurl.starts_with("#") {
- let f = decode_component(rawurl.slice(
- 1,
- rawurl.len()));
- return Ok((~[], Some(f)));
- } else {
- return Ok((~[], None));
- }
- }
- let (q, r) = split_char_first(rawurl.slice(1, rawurl.len()), '#');
- let f = if r.len() != 0 {
- Some(decode_component(r)) } else { None };
- return Ok((query_from_str(q), f));
-}
-
-/**
- * Parses a URL, converting it from a string to `Url` representation.
- *
- * # Arguments
- *
- * `rawurl` - a string representing the full URL, including scheme.
- *
- * # Returns
- *
- * A `Url` struct type representing the URL.
- */
-pub fn from_str(rawurl: &str) -> Result<Url, ~str> {
- // scheme
- let (scheme, rest) = match get_scheme(rawurl) {
- Ok(val) => val,
- Err(e) => return Err(e),
- };
-
- // authority
- let (userinfo, host, port, rest) = match get_authority(rest) {
- Ok(val) => val,
- Err(e) => return Err(e),
- };
-
- // path
- let has_authority = if host == ~"" { false } else { true };
- let (path, rest) = match get_path(rest, has_authority) {
- Ok(val) => val,
- Err(e) => return Err(e),
- };
-
- // query and fragment
- let (query, fragment) = match get_query_fragment(rest) {
- Ok(val) => val,
- Err(e) => return Err(e),
- };
-
- Ok(Url::new(scheme, userinfo, host, port, path, query, fragment))
-}
-
-pub fn path_from_str(rawpath: &str) -> Result<Path, ~str> {
- let (path, rest) = match get_path(rawpath, false) {
- Ok(val) => val,
- Err(e) => return Err(e)
- };
-
- // query and fragment
- let (query, fragment) = match get_query_fragment(rest) {
- Ok(val) => val,
- Err(e) => return Err(e),
- };
-
- Ok(Path{ path: path, query: query, fragment: fragment })
-}
-
-impl FromStr for Url {
- fn from_str(s: &str) -> Option<Url> {
- match from_str(s) {
- Ok(url) => Some(url),
- Err(_) => None
- }
- }
-}
-
-impl FromStr for Path {
- fn from_str(s: &str) -> Option<Path> {
- match path_from_str(s) {
- Ok(path) => Some(path),
- Err(_) => None
- }
- }
-}
-
-impl fmt::Show for Url {
- /**
- * Converts a URL from `Url` to string representation.
- *
- * # Arguments
- *
- * `url` - a URL.
- *
- * # Returns
- *
- * A string that contains the formatted URL. Note that this will usually
- * be an inverse of `from_str` but might strip out unneeded separators;
- * for example, "http://somehost.com?", when parsed and formatted, will
- * result in just "http://somehost.com".
- */
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- try!(write!(f.buf, "{}:", self.scheme));
-
- if !self.host.is_empty() {
- try!(write!(f.buf, "//"));
- match self.user {
- Some(ref user) => try!(write!(f.buf, "{}", *user)),
- None => {}
- }
- match self.port {
- Some(ref port) => try!(write!(f.buf, "{}:{}", self.host,
- *port)),
- None => try!(write!(f.buf, "{}", self.host)),
- }
- }
-
- try!(write!(f.buf, "{}", self.path));
-
- if !self.query.is_empty() {
- try!(write!(f.buf, "?{}", query_to_str(&self.query)));
- }
-
- match self.fragment {
- Some(ref fragment) => write!(f.buf, "\\#{}",
- encode_component(*fragment)),
- None => Ok(()),
- }
- }
-}
-
-impl fmt::Show for Path {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- try!(write!(f.buf, "{}", self.path));
- if !self.query.is_empty() {
- try!(write!(f.buf, "?{}", self.query))
- }
-
- match self.fragment {
- Some(ref fragment) => {
- write!(f.buf, "\\#{}", encode_component(*fragment))
- }
- None => Ok(())
- }
- }
-}
-
-impl<S: Writer> Hash<S> for Url {
- fn hash(&self, state: &mut S) {
- self.to_str().hash(state)
- }
-}
-
-impl<S: Writer> Hash<S> for Path {
- fn hash(&self, state: &mut S) {
- self.to_str().hash(state)
- }
-}
-
-// Put a few tests outside of the 'test' module so they can test the internal
-// functions and those functions don't need 'pub'
-
-#[test]
-fn test_split_char_first() {
- let (u,v) = split_char_first("hello, sweet world", ',');
- assert_eq!(u, ~"hello");
- assert_eq!(v, ~" sweet world");
-
- let (u,v) = split_char_first("hello sweet world", ',');
- assert_eq!(u, ~"hello sweet world");
- assert_eq!(v, ~"");
-}
-
-#[test]
-fn test_get_authority() {
- let (u, h, p, r) = get_authority(
- "//user:pass@rust-lang.org/something").unwrap();
- assert_eq!(u, Some(UserInfo::new(~"user", Some(~"pass"))));
- assert_eq!(h, ~"rust-lang.org");
- assert!(p.is_none());
- assert_eq!(r, ~"/something");
-
- let (u, h, p, r) = get_authority(
- "//rust-lang.org:8000?something").unwrap();
- assert!(u.is_none());
- assert_eq!(h, ~"rust-lang.org");
- assert_eq!(p, Some(~"8000"));
- assert_eq!(r, ~"?something");
-
- let (u, h, p, r) = get_authority(
- "//rust-lang.org#blah").unwrap();
- assert!(u.is_none());
- assert_eq!(h, ~"rust-lang.org");
- assert!(p.is_none());
- assert_eq!(r, ~"#blah");
-
- // ipv6 tests
- let (_, h, _, _) = get_authority(
- "//2001:0db8:85a3:0042:0000:8a2e:0370:7334#blah").unwrap();
- assert_eq!(h, ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334");
-
- let (_, h, p, _) = get_authority(
- "//2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000#blah").unwrap();
- assert_eq!(h, ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334");
- assert_eq!(p, Some(~"8000"));
-
- let (u, h, p, _) = get_authority(
- "//us:p@2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000#blah"
- ).unwrap();
- assert_eq!(u, Some(UserInfo::new(~"us", Some(~"p"))));
- assert_eq!(h, ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334");
- assert_eq!(p, Some(~"8000"));
-
- // invalid authorities;
- assert!(get_authority("//user:pass@rust-lang:something").is_err());
- assert!(get_authority("//user@rust-lang:something:/path").is_err());
- assert!(get_authority(
- "//2001:0db8:85a3:0042:0000:8a2e:0370:7334:800a").is_err());
- assert!(get_authority(
- "//2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000:00").is_err());
-
- // these parse as empty, because they don't start with '//'
- let (_, h, _, _) = get_authority("user:pass@rust-lang").unwrap();
- assert_eq!(h, ~"");
- let (_, h, _, _) = get_authority("rust-lang.org").unwrap();
- assert_eq!(h, ~"");
-}
-
-#[test]
-fn test_get_path() {
- let (p, r) = get_path("/something+%20orother", true).unwrap();
- assert_eq!(p, ~"/something+ orother");
- assert_eq!(r, ~"");
- let (p, r) = get_path("test@email.com#fragment", false).unwrap();
- assert_eq!(p, ~"test@email.com");
- assert_eq!(r, ~"#fragment");
- let (p, r) = get_path("/gen/:addr=?q=v", false).unwrap();
- assert_eq!(p, ~"/gen/:addr=");
- assert_eq!(r, ~"?q=v");
-
- //failure cases
- assert!(get_path("something?q", true).is_err());
-}
-
-#[cfg(test)]
-mod tests {
-
- use super::*;
-
- use collections::HashMap;
-
- #[test]
- fn test_url_parse() {
- let url = ~"http://user:pass@rust-lang.org:8080/doc/~u?s=v#something";
-
- let up = from_str(url);
- let u = up.unwrap();
- assert_eq!(&u.scheme, &~"http");
- assert_eq!(&u.user, &Some(UserInfo::new(~"user", Some(~"pass"))));
- assert_eq!(&u.host, &~"rust-lang.org");
- assert_eq!(&u.port, &Some(~"8080"));
- assert_eq!(&u.path, &~"/doc/~u");
- assert_eq!(&u.query, &~[(~"s", ~"v")]);
- assert_eq!(&u.fragment, &Some(~"something"));
- }
-
- #[test]
- fn test_path_parse() {
- let path = ~"/doc/~u?s=v#something";
-
- let up = path_from_str(path);
- let u = up.unwrap();
- assert_eq!(&u.path, &~"/doc/~u");
- assert_eq!(&u.query, &~[(~"s", ~"v")]);
- assert_eq!(&u.fragment, &Some(~"something"));
- }
-
- #[test]
- fn test_url_parse_host_slash() {
- let urlstr = ~"http://0.42.42.42/";
- let url = from_str(urlstr).unwrap();
- assert!(url.host == ~"0.42.42.42");
- assert!(url.path == ~"/");
- }
-
- #[test]
- fn test_path_parse_host_slash() {
- let pathstr = ~"/";
- let path = path_from_str(pathstr).unwrap();
- assert!(path.path == ~"/");
- }
-
- #[test]
- fn test_url_host_with_port() {
- let urlstr = ~"scheme://host:1234";
- let url = from_str(urlstr).unwrap();
- assert_eq!(&url.scheme, &~"scheme");
- assert_eq!(&url.host, &~"host");
- assert_eq!(&url.port, &Some(~"1234"));
- assert_eq!(&url.path, &~""); // is empty path really correct? Other tests think so
- let urlstr = ~"scheme://host:1234/";
- let url = from_str(urlstr).unwrap();
- assert_eq!(&url.scheme, &~"scheme");
- assert_eq!(&url.host, &~"host");
- assert_eq!(&url.port, &Some(~"1234"));
- assert_eq!(&url.path, &~"/");
- }
-
- #[test]
- fn test_url_with_underscores() {
- let urlstr = ~"http://dotcom.com/file_name.html";
- let url = from_str(urlstr).unwrap();
- assert!(url.path == ~"/file_name.html");
- }
-
- #[test]
- fn test_path_with_underscores() {
- let pathstr = ~"/file_name.html";
- let path = path_from_str(pathstr).unwrap();
- assert!(path.path == ~"/file_name.html");
- }
-
- #[test]
- fn test_url_with_dashes() {
- let urlstr = ~"http://dotcom.com/file-name.html";
- let url = from_str(urlstr).unwrap();
- assert!(url.path == ~"/file-name.html");
- }
-
- #[test]
- fn test_path_with_dashes() {
- let pathstr = ~"/file-name.html";
- let path = path_from_str(pathstr).unwrap();
- assert!(path.path == ~"/file-name.html");
- }
-
- #[test]
- fn test_no_scheme() {
- assert!(get_scheme("noschemehere.html").is_err());
- }
-
- #[test]
- fn test_invalid_scheme_errors() {
- assert!(from_str("99://something").is_err());
- assert!(from_str("://something").is_err());
- }
-
- #[test]
- fn test_full_url_parse_and_format() {
- let url = ~"http://user:pass@rust-lang.org/doc?s=v#something";
- assert_eq!(from_str(url).unwrap().to_str(), url);
- }
-
- #[test]
- fn test_userless_url_parse_and_format() {
- let url = ~"http://rust-lang.org/doc?s=v#something";
- assert_eq!(from_str(url).unwrap().to_str(), url);
- }
-
- #[test]
- fn test_queryless_url_parse_and_format() {
- let url = ~"http://user:pass@rust-lang.org/doc#something";
- assert_eq!(from_str(url).unwrap().to_str(), url);
- }
-
- #[test]
- fn test_empty_query_url_parse_and_format() {
- let url = ~"http://user:pass@rust-lang.org/doc?#something";
- let should_be = ~"http://user:pass@rust-lang.org/doc#something";
- assert_eq!(from_str(url).unwrap().to_str(), should_be);
- }
-
- #[test]
- fn test_fragmentless_url_parse_and_format() {
- let url = ~"http://user:pass@rust-lang.org/doc?q=v";
- assert_eq!(from_str(url).unwrap().to_str(), url);
- }
-
- #[test]
- fn test_minimal_url_parse_and_format() {
- let url = ~"http://rust-lang.org/doc";
- assert_eq!(from_str(url).unwrap().to_str(), url);
- }
-
- #[test]
- fn test_url_with_port_parse_and_format() {
- let url = ~"http://rust-lang.org:80/doc";
- assert_eq!(from_str(url).unwrap().to_str(), url);
- }
-
- #[test]
- fn test_scheme_host_only_url_parse_and_format() {
- let url = ~"http://rust-lang.org";
- assert_eq!(from_str(url).unwrap().to_str(), url);
- }
-
- #[test]
- fn test_pathless_url_parse_and_format() {
- let url = ~"http://user:pass@rust-lang.org?q=v#something";
- assert_eq!(from_str(url).unwrap().to_str(), url);
- }
-
- #[test]
- fn test_scheme_host_fragment_only_url_parse_and_format() {
- let url = ~"http://rust-lang.org#something";
- assert_eq!(from_str(url).unwrap().to_str(), url);
- }
-
- #[test]
- fn test_url_component_encoding() {
- let url = ~"http://rust-lang.org/doc%20uments?ba%25d%20=%23%26%2B";
- let u = from_str(url).unwrap();
- assert!(u.path == ~"/doc uments");
- assert!(u.query == ~[(~"ba%d ", ~"#&+")]);
- }
-
- #[test]
- fn test_path_component_encoding() {
- let path = ~"/doc%20uments?ba%25d%20=%23%26%2B";
- let p = path_from_str(path).unwrap();
- assert!(p.path == ~"/doc uments");
- assert!(p.query == ~[(~"ba%d ", ~"#&+")]);
- }
-
- #[test]
- fn test_url_without_authority() {
- let url = ~"mailto:test@email.com";
- assert_eq!(from_str(url).unwrap().to_str(), url);
- }
-
- #[test]
- fn test_encode() {
- assert_eq!(encode(""), ~"");
- assert_eq!(encode("http://example.com"), ~"http://example.com");
- assert_eq!(encode("foo bar% baz"), ~"foo%20bar%25%20baz");
- assert_eq!(encode(" "), ~"%20");
- assert_eq!(encode("!"), ~"!");
- assert_eq!(encode("\""), ~"\"");
- assert_eq!(encode("#"), ~"#");
- assert_eq!(encode("$"), ~"$");
- assert_eq!(encode("%"), ~"%25");
- assert_eq!(encode("&"), ~"&");
- assert_eq!(encode("'"), ~"%27");
- assert_eq!(encode("("), ~"(");
- assert_eq!(encode(")"), ~")");
- assert_eq!(encode("*"), ~"*");
- assert_eq!(encode("+"), ~"+");
- assert_eq!(encode(","), ~",");
- assert_eq!(encode("/"), ~"/");
- assert_eq!(encode(":"), ~":");
- assert_eq!(encode(";"), ~";");
- assert_eq!(encode("="), ~"=");
- assert_eq!(encode("?"), ~"?");
- assert_eq!(encode("@"), ~"@");
- assert_eq!(encode("["), ~"[");
- assert_eq!(encode("]"), ~"]");
- }
-
- #[test]
- fn test_encode_component() {
- assert_eq!(encode_component(""), ~"");
- assert!(encode_component("http://example.com") ==
- ~"http%3A%2F%2Fexample.com");
- assert!(encode_component("foo bar% baz") ==
- ~"foo%20bar%25%20baz");
- assert_eq!(encode_component(" "), ~"%20");
- assert_eq!(encode_component("!"), ~"%21");
- assert_eq!(encode_component("#"), ~"%23");
- assert_eq!(encode_component("$"), ~"%24");
- assert_eq!(encode_component("%"), ~"%25");
- assert_eq!(encode_component("&"), ~"%26");
- assert_eq!(encode_component("'"), ~"%27");
- assert_eq!(encode_component("("), ~"%28");
- assert_eq!(encode_component(")"), ~"%29");
- assert_eq!(encode_component("*"), ~"%2A");
- assert_eq!(encode_component("+"), ~"%2B");
- assert_eq!(encode_component(","), ~"%2C");
- assert_eq!(encode_component("/"), ~"%2F");
- assert_eq!(encode_component(":"), ~"%3A");
- assert_eq!(encode_component(";"), ~"%3B");
- assert_eq!(encode_component("="), ~"%3D");
- assert_eq!(encode_component("?"), ~"%3F");
- assert_eq!(encode_component("@"), ~"%40");
- assert_eq!(encode_component("["), ~"%5B");
- assert_eq!(encode_component("]"), ~"%5D");
- }
-
- #[test]
- fn test_decode() {
- assert_eq!(decode(""), ~"");
- assert_eq!(decode("abc/def 123"), ~"abc/def 123");
- assert_eq!(decode("abc%2Fdef%20123"), ~"abc%2Fdef 123");
- assert_eq!(decode("%20"), ~" ");
- assert_eq!(decode("%21"), ~"%21");
- assert_eq!(decode("%22"), ~"%22");
- assert_eq!(decode("%23"), ~"%23");
- assert_eq!(decode("%24"), ~"%24");
- assert_eq!(decode("%25"), ~"%");
- assert_eq!(decode("%26"), ~"%26");
- assert_eq!(decode("%27"), ~"'");
- assert_eq!(decode("%28"), ~"%28");
- assert_eq!(decode("%29"), ~"%29");
- assert_eq!(decode("%2A"), ~"%2A");
- assert_eq!(decode("%2B"), ~"%2B");
- assert_eq!(decode("%2C"), ~"%2C");
- assert_eq!(decode("%2F"), ~"%2F");
- assert_eq!(decode("%3A"), ~"%3A");
- assert_eq!(decode("%3B"), ~"%3B");
- assert_eq!(decode("%3D"), ~"%3D");
- assert_eq!(decode("%3F"), ~"%3F");
- assert_eq!(decode("%40"), ~"%40");
- assert_eq!(decode("%5B"), ~"%5B");
- assert_eq!(decode("%5D"), ~"%5D");
- }
-
- #[test]
- fn test_decode_component() {
- assert_eq!(decode_component(""), ~"");
- assert_eq!(decode_component("abc/def 123"), ~"abc/def 123");
- assert_eq!(decode_component("abc%2Fdef%20123"), ~"abc/def 123");
- assert_eq!(decode_component("%20"), ~" ");
- assert_eq!(decode_component("%21"), ~"!");
- assert_eq!(decode_component("%22"), ~"\"");
- assert_eq!(decode_component("%23"), ~"#");
- assert_eq!(decode_component("%24"), ~"$");
- assert_eq!(decode_component("%25"), ~"%");
- assert_eq!(decode_component("%26"), ~"&");
- assert_eq!(decode_component("%27"), ~"'");
- assert_eq!(decode_component("%28"), ~"(");
- assert_eq!(decode_component("%29"), ~")");
- assert_eq!(decode_component("%2A"), ~"*");
- assert_eq!(decode_component("%2B"), ~"+");
- assert_eq!(decode_component("%2C"), ~",");
- assert_eq!(decode_component("%2F"), ~"/");
- assert_eq!(decode_component("%3A"), ~":");
- assert_eq!(decode_component("%3B"), ~";");
- assert_eq!(decode_component("%3D"), ~"=");
- assert_eq!(decode_component("%3F"), ~"?");
- assert_eq!(decode_component("%40"), ~"@");
- assert_eq!(decode_component("%5B"), ~"[");
- assert_eq!(decode_component("%5D"), ~"]");
- }
-
- #[test]
- fn test_encode_form_urlencoded() {
- let mut m = HashMap::new();
- assert_eq!(encode_form_urlencoded(&m), ~"");
-
- m.insert(~"", ~[]);
- m.insert(~"foo", ~[]);
- assert_eq!(encode_form_urlencoded(&m), ~"");
-
- let mut m = HashMap::new();
- m.insert(~"foo", ~[~"bar", ~"123"]);
- assert_eq!(encode_form_urlencoded(&m), ~"foo=bar&foo=123");
-
- let mut m = HashMap::new();
- m.insert(~"foo bar", ~[~"abc", ~"12 = 34"]);
- assert!(encode_form_urlencoded(&m) ==
- ~"foo+bar=abc&foo+bar=12+%3D+34");
- }
-
- #[test]
- fn test_decode_form_urlencoded() {
- assert_eq!(decode_form_urlencoded([]).len(), 0);
-
- let s = "a=1&foo+bar=abc&foo+bar=12+%3D+34".as_bytes();
- let form = decode_form_urlencoded(s);
- assert_eq!(form.len(), 2);
- assert_eq!(form.get(&~"a"), &~[~"1"]);
- assert_eq!(form.get(&~"foo bar"), &~[~"abc", ~"12 = 34"]);
- }
-}
+++ /dev/null
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[allow(missing_doc)];
-#[allow(visible_private_types)];
-
-use serialize::json;
-use serialize::json::ToJson;
-use serialize::{Encoder, Encodable, Decoder, Decodable};
-use sync::{Arc,RWArc};
-use collections::TreeMap;
-use std::str;
-use std::io;
-use std::io::{File, MemWriter};
-
-/**
-*
-* This is a loose clone of the [fbuild build system](https://github.com/felix-lang/fbuild),
-* made a touch more generic (not wired to special cases on files) and much
-* less metaprogram-y due to rust's comparative weakness there, relative to
-* python.
-*
-* It's based around _imperative builds_ that happen to have some function
-* calls cached. That is, it's _just_ a mechanism for describing cached
-* functions. This makes it much simpler and smaller than a "build system"
-* that produces an IR and evaluates it. The evaluation order is normal
-* function calls. Some of them just return really quickly.
-*
-* A cached function consumes and produces a set of _works_. A work has a
-* name, a kind (that determines how the value is to be checked for
-* freshness) and a value. Works must also be (de)serializable. Some
-* examples of works:
-*
-* kind name value
-* ------------------------
-* cfg os linux
-* file foo.c <sha1>
-* url foo.com <etag>
-*
-* Works are conceptually single units, but we store them most of the time
-* in maps of the form (type,name) => value. These are WorkMaps.
-*
-* A cached function divides the works it's interested in into inputs and
-* outputs, and subdivides those into declared (input) works and
-* discovered (input and output) works.
-*
-* A _declared_ input or is one that is given to the workcache before
-* any work actually happens, in the "prep" phase. Even when a function's
-* work-doing part (the "exec" phase) never gets called, it has declared
-* inputs, which can be checked for freshness (and potentially
-* used to determine that the function can be skipped).
-*
-* The workcache checks _all_ works for freshness, but uses the set of
-* discovered outputs from the _previous_ exec (which it will re-discover
-* and re-record each time the exec phase runs).
-*
-* Therefore the discovered works cached in the db might be a
-* mis-approximation of the current discoverable works, but this is ok for
-* the following reason: we assume that if an artifact A changed from
-* depending on B,C,D to depending on B,C,D,E, then A itself changed (as
-* part of the change-in-dependencies), so we will be ok.
-*
-* Each function has a single discriminated output work called its _result_.
-* This is only different from other works in that it is returned, by value,
-* from a call to the cacheable function; the other output works are used in
-* passing to invalidate dependencies elsewhere in the cache, but do not
-* otherwise escape from a function invocation. Most functions only have one
-* output work anyways.
-*
-* A database (the central store of a workcache) stores a mappings:
-*
-* (fn_name,{declared_input}) => ({discovered_input},
-* {discovered_output},result)
-*
-* (Note: fbuild, which workcache is based on, has the concept of a declared
-* output as separate from a discovered output. This distinction exists only
-* as an artifact of how fbuild works: via annotations on function types
-* and metaprogramming, with explicit dependency declaration as a fallback.
-* Workcache is more explicit about dependencies, and as such treats all
-* outputs the same, as discovered-during-the-last-run.)
-*
-*/
-
-#[deriving(Clone, Eq, Encodable, Decodable, Ord, TotalOrd, TotalEq)]
-struct WorkKey {
- kind: ~str,
- name: ~str
-}
-
-impl WorkKey {
- pub fn new(kind: &str, name: &str) -> WorkKey {
- WorkKey {
- kind: kind.to_owned(),
- name: name.to_owned(),
- }
- }
-}
-
-// FIXME #8883: The key should be a WorkKey and not a ~str.
-// This is working around some JSON weirdness.
-#[deriving(Clone, Eq, Encodable, Decodable)]
-struct WorkMap(TreeMap<~str, KindMap>);
-
-#[deriving(Clone, Eq, Encodable, Decodable)]
-struct KindMap(TreeMap<~str, ~str>);
-
-impl WorkMap {
- fn new() -> WorkMap { WorkMap(TreeMap::new()) }
-
- fn insert_work_key(&mut self, k: WorkKey, val: ~str) {
- let WorkKey { kind, name } = k;
- let WorkMap(ref mut map) = *self;
- match map.find_mut(&name) {
- Some(&KindMap(ref mut m)) => { m.insert(kind, val); return; }
- None => ()
- }
- let mut new_map = TreeMap::new();
- new_map.insert(kind, val);
- map.insert(name, KindMap(new_map));
- }
-}
-
-pub struct Database {
- priv db_filename: Path,
- priv db_cache: TreeMap<~str, ~str>,
- db_dirty: bool
-}
-
-impl Database {
-
- pub fn new(p: Path) -> Database {
- let mut rslt = Database {
- db_filename: p,
- db_cache: TreeMap::new(),
- db_dirty: false
- };
- if rslt.db_filename.exists() {
- rslt.load();
- }
- rslt
- }
-
- pub fn prepare(&self,
- fn_name: &str,
- declared_inputs: &WorkMap)
- -> Option<(WorkMap, WorkMap, ~str)> {
- let k = json_encode(&(fn_name, declared_inputs));
- match self.db_cache.find(&k) {
- None => None,
- Some(v) => Some(json_decode(*v))
- }
- }
-
- pub fn cache(&mut self,
- fn_name: &str,
- declared_inputs: &WorkMap,
- discovered_inputs: &WorkMap,
- discovered_outputs: &WorkMap,
- result: &str) {
- let k = json_encode(&(fn_name, declared_inputs));
- let v = json_encode(&(discovered_inputs,
- discovered_outputs,
- result));
- self.db_cache.insert(k,v);
- self.db_dirty = true
- }
-
- // FIXME #4330: This should have &mut self and should set self.db_dirty to false.
- fn save(&self) -> io::IoResult<()> {
- let mut f = File::create(&self.db_filename);
- self.db_cache.to_json().to_pretty_writer(&mut f)
- }
-
- fn load(&mut self) {
- assert!(!self.db_dirty);
- assert!(self.db_filename.exists());
- match File::open(&self.db_filename) {
- Err(e) => fail!("Couldn't load workcache database {}: {}",
- self.db_filename.display(),
- e),
- Ok(mut stream) => {
- match json::from_reader(&mut stream) {
- Err(e) => fail!("Couldn't parse workcache database (from file {}): {}",
- self.db_filename.display(), e.to_str()),
- Ok(r) => {
- let mut decoder = json::Decoder::new(r);
- self.db_cache = Decodable::decode(&mut decoder);
- }
- }
- }
- }
- }
-}
-
-#[unsafe_destructor]
-impl Drop for Database {
- fn drop(&mut self) {
- if self.db_dirty {
- // FIXME: is failing the right thing to do here
- self.save().unwrap();
- }
- }
-}
-
-pub type FreshnessMap = TreeMap<~str,extern fn(&str,&str)->bool>;
-
-#[deriving(Clone)]
-pub struct Context {
- db: RWArc<Database>,
- priv cfg: Arc<json::Object>,
- /// Map from kinds (source, exe, url, etc.) to a freshness function.
- /// The freshness function takes a name (e.g. file path) and value
- /// (e.g. hash of file contents) and determines whether it's up-to-date.
- /// For example, in the file case, this would read the file off disk,
- /// hash it, and return the result of comparing the given hash and the
- /// read hash for equality.
- priv freshness: Arc<FreshnessMap>
-}
-
-pub struct Prep<'a> {
- priv ctxt: &'a Context,
- priv fn_name: &'a str,
- priv declared_inputs: WorkMap,
-}
-
-pub struct Exec {
- priv discovered_inputs: WorkMap,
- priv discovered_outputs: WorkMap
-}
-
-enum Work<'a, T> {
- WorkValue(T),
- WorkFromTask(&'a Prep<'a>, Receiver<(Exec, T)>),
-}
-
-fn json_encode<'a, T:Encodable<json::Encoder<'a>>>(t: &T) -> ~str {
- let mut writer = MemWriter::new();
- let mut encoder = json::Encoder::new(&mut writer as &mut io::Writer);
- t.encode(&mut encoder);
- str::from_utf8_owned(writer.unwrap()).unwrap()
-}
-
-// FIXME(#5121)
-fn json_decode<T:Decodable<json::Decoder>>(s: &str) -> T {
- debug!("json decoding: {}", s);
- let j = json::from_str(s).unwrap();
- let mut decoder = json::Decoder::new(j);
- Decodable::decode(&mut decoder)
-}
-
-impl Context {
-
- pub fn new(db: RWArc<Database>,
- cfg: Arc<json::Object>) -> Context {
- Context::new_with_freshness(db, cfg, Arc::new(TreeMap::new()))
- }
-
- pub fn new_with_freshness(db: RWArc<Database>,
- cfg: Arc<json::Object>,
- freshness: Arc<FreshnessMap>) -> Context {
- Context {
- db: db,
- cfg: cfg,
- freshness: freshness
- }
- }
-
- pub fn prep<'a>(&'a self, fn_name: &'a str) -> Prep<'a> {
- Prep::new(self, fn_name)
- }
-
- pub fn with_prep<'a,
- T>(
- &'a self,
- fn_name: &'a str,
- blk: |p: &mut Prep| -> T)
- -> T {
- let mut p = self.prep(fn_name);
- blk(&mut p)
- }
-
-}
-
-impl Exec {
- pub fn discover_input(&mut self,
- dependency_kind: &str,
- dependency_name: &str,
- dependency_val: &str) {
- debug!("Discovering input {} {} {}", dependency_kind, dependency_name, dependency_val);
- self.discovered_inputs.insert_work_key(WorkKey::new(dependency_kind, dependency_name),
- dependency_val.to_owned());
- }
- pub fn discover_output(&mut self,
- dependency_kind: &str,
- dependency_name: &str,
- dependency_val: &str) {
- debug!("Discovering output {} {} {}", dependency_kind, dependency_name, dependency_val);
- self.discovered_outputs.insert_work_key(WorkKey::new(dependency_kind, dependency_name),
- dependency_val.to_owned());
- }
-
- // returns pairs of (kind, name)
- pub fn lookup_discovered_inputs(&self) -> ~[(~str, ~str)] {
- let mut rs = ~[];
- let WorkMap(ref discovered_inputs) = self.discovered_inputs;
- for (k, v) in discovered_inputs.iter() {
- let KindMap(ref vmap) = *v;
- for (k1, _) in vmap.iter() {
- rs.push((k1.clone(), k.clone()));
- }
- }
- rs
- }
-}
-
-impl<'a> Prep<'a> {
- fn new(ctxt: &'a Context, fn_name: &'a str) -> Prep<'a> {
- Prep {
- ctxt: ctxt,
- fn_name: fn_name,
- declared_inputs: WorkMap::new()
- }
- }
-
- pub fn lookup_declared_inputs(&self) -> ~[~str] {
- let mut rs = ~[];
- let WorkMap(ref declared_inputs) = self.declared_inputs;
- for (_, v) in declared_inputs.iter() {
- let KindMap(ref vmap) = *v;
- for (inp, _) in vmap.iter() {
- rs.push(inp.clone());
- }
- }
- rs
- }
-}
-
-impl<'a> Prep<'a> {
- pub fn declare_input(&mut self, kind: &str, name: &str, val: &str) {
- debug!("Declaring input {} {} {}", kind, name, val);
- self.declared_inputs.insert_work_key(WorkKey::new(kind, name),
- val.to_owned());
- }
-
- fn is_fresh(&self, cat: &str, kind: &str,
- name: &str, val: &str) -> bool {
- let k = kind.to_owned();
- let f = self.ctxt.freshness.get().find(&k);
- debug!("freshness for: {}/{}/{}/{}", cat, kind, name, val)
- let fresh = match f {
- None => fail!("missing freshness-function for '{}'", kind),
- Some(f) => (*f)(name, val)
- };
- if fresh {
- info!("{} {}:{} is fresh", cat, kind, name);
- } else {
- info!("{} {}:{} is not fresh", cat, kind, name);
- }
- fresh
- }
-
- fn all_fresh(&self, cat: &str, map: &WorkMap) -> bool {
- let WorkMap(ref map) = *map;
- for (k_name, kindmap) in map.iter() {
- let KindMap(ref kindmap_) = *kindmap;
- for (k_kind, v) in kindmap_.iter() {
- if ! self.is_fresh(cat, *k_kind, *k_name, *v) {
- return false;
- }
- }
- }
- return true;
- }
-
- pub fn exec<'a, T:Send +
- Encodable<json::Encoder<'a>> +
- Decodable<json::Decoder>>(
- &'a self, blk: proc(&mut Exec) -> T) -> T {
- self.exec_work(blk).unwrap()
- }
-
- fn exec_work<'a, T:Send +
- Encodable<json::Encoder<'a>> +
- Decodable<json::Decoder>>( // FIXME(#5121)
- &'a self, blk: proc(&mut Exec) -> T) -> Work<'a, T> {
- let mut bo = Some(blk);
-
- debug!("exec_work: looking up {} and {:?}", self.fn_name,
- self.declared_inputs);
- let cached = self.ctxt.db.read(|db| {
- db.prepare(self.fn_name, &self.declared_inputs)
- });
-
- match cached {
- Some((ref disc_in, ref disc_out, ref res))
- if self.all_fresh("declared input",&self.declared_inputs) &&
- self.all_fresh("discovered input", disc_in) &&
- self.all_fresh("discovered output", disc_out) => {
- debug!("Cache hit!");
- debug!("Trying to decode: {:?} / {:?} / {}",
- disc_in, disc_out, *res);
- Work::from_value(json_decode(*res))
- }
-
- _ => {
- debug!("Cache miss!");
- let (tx, rx) = channel();
- let blk = bo.take_unwrap();
-
- // FIXME: What happens if the task fails?
- spawn(proc() {
- let mut exe = Exec {
- discovered_inputs: WorkMap::new(),
- discovered_outputs: WorkMap::new(),
- };
- let v = blk(&mut exe);
- tx.send((exe, v));
- });
- Work::from_task(self, rx)
- }
- }
- }
-}
-
-impl<'a, T:Send +
- Encodable<json::Encoder<'a>> +
- Decodable<json::Decoder>>
- Work<'a, T> { // FIXME(#5121)
-
- pub fn from_value(elt: T) -> Work<'a, T> {
- WorkValue(elt)
- }
- pub fn from_task(prep: &'a Prep<'a>, port: Receiver<(Exec, T)>)
- -> Work<'a, T> {
- WorkFromTask(prep, port)
- }
-
- pub fn unwrap(self) -> T {
- match self {
- WorkValue(v) => v,
- WorkFromTask(prep, port) => {
- let (exe, v) = port.recv();
- let s = json_encode(&v);
- prep.ctxt.db.write(|db| {
- db.cache(prep.fn_name,
- &prep.declared_inputs,
- &exe.discovered_inputs,
- &exe.discovered_outputs,
- s)
- });
- v
- }
- }
- }
-}
-
-
-#[test]
-#[cfg(not(target_os="android"))] // FIXME(#10455)
-fn test() {
- use std::os;
- use std::io::{fs, Process};
- use std::str::from_utf8_owned;
-
- // Create a path to a new file 'filename' in the directory in which
- // this test is running.
- fn make_path(filename: ~str) -> Path {
- let pth = os::self_exe_path().expect("workcache::test failed").with_filename(filename);
- if pth.exists() {
- fs::unlink(&pth).unwrap();
- }
- return pth;
- }
-
- let pth = make_path(~"foo.c");
- File::create(&pth).write(bytes!("int main() { return 0; }")).unwrap();
-
- let db_path = make_path(~"db.json");
-
- let cx = Context::new(RWArc::new(Database::new(db_path)),
- Arc::new(TreeMap::new()));
-
- let s = cx.with_prep("test1", |prep| {
-
- let subcx = cx.clone();
- let pth = pth.clone();
-
- let contents = File::open(&pth).read_to_end().unwrap();
- let file_content = from_utf8_owned(contents).unwrap();
-
- // FIXME (#9639): This needs to handle non-utf8 paths
- prep.declare_input("file", pth.as_str().unwrap(), file_content);
- prep.exec(proc(_exe) {
- let out = make_path(~"foo.o");
- // FIXME (#9639): This needs to handle non-utf8 paths
- Process::status("gcc", [pth.as_str().unwrap().to_owned(),
- ~"-o",
- out.as_str().unwrap().to_owned()]).unwrap();
-
- let _proof_of_concept = subcx.prep("subfn");
- // Could run sub-rules inside here.
-
- // FIXME (#9639): This needs to handle non-utf8 paths
- out.as_str().unwrap().to_owned()
- })
- });
-
- println!("{}", s);
-}
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
-#[allow(missing_doc)];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
+#[feature(phase)];
+
+#[cfg(test)] #[phase(syntax, link)] extern crate log;
-extern crate extra;
use std::libc::{c_void, size_t, c_int};
use std::libc;
-use extra::c_vec::CVec;
+use std::c_vec::CVec;
pub mod rustrt {
use std::libc::{c_int, c_void, size_t};
#[cfg(test)]
mod tests {
+ #[allow(deprecated_owned_vector)];
extern crate rand;
use super::{inflate_bytes, deflate_bytes};
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
#[feature(macro_registrar, managed_boxes)];
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
#[allow(missing_doc)];
+#[allow(deprecated_owned_vector)];
-#[feature(globs)];
+#[feature(globs, phase)];
+
+#[cfg(test)] #[phase(syntax, link)] extern crate log;
use std::cmp::Eq;
use std::result::{Err, Ok};
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
+#[allow(deprecated_owned_vector)];
use std::cell::Cell;
use std::{cmp, os, path};
unsafe { *sp = 0; }
regs[4] = arg as uint;
+ regs[5] = procedure.code as uint;
+ regs[6] = procedure.env as uint;
regs[29] = sp as uint;
regs[25] = fptr as uint;
regs[31] = fptr as uint;
html_root_url = "http://static.rust-lang.org/doc/master")];
// NB this does *not* include globs, please keep it that way.
-#[feature(macro_rules)];
+#[feature(macro_rules, phase)];
#[allow(visible_private_types)];
+#[allow(deprecated_owned_vector)];
+#[cfg(test)] #[phase(syntax, link)] extern crate log;
extern crate rand;
use std::mem::replace;
use std::any::Any;
use std::cast;
-use std::rt::env;
+use std::raw;
use std::rt::Runtime;
+use std::rt::env;
use std::rt::local::Local;
use std::rt::rtio;
+use std::rt::stack;
use std::rt::task::{Task, BlockedTask, SendMessage};
use std::task::TaskOpts;
use std::unstable::mutex::NativeMutex;
-use std::raw;
use context::Context;
use coroutine::Coroutine;
f: proc()) -> ~GreenTask {
let TaskOpts {
notify_chan, name, stack_size,
- stderr, stdout, logger,
+ stderr, stdout,
} = opts;
let mut green = GreenTask::new(pool, stack_size, f);
{
let task = green.task.get_mut_ref();
task.name = name;
- task.logger = logger;
task.stderr = stderr;
task.stdout = stdout;
match notify_chan {
let c = self.coroutine.as_ref()
.expect("GreenTask.stack_bounds called without a coroutine");
- (c.current_stack_segment.start() as uint,
+ // Don't return the red zone as part of the usable stack of this task,
+ // it's essentially an implementation detail.
+ (c.current_stack_segment.start() as uint + stack::RED_ZONE,
c.current_stack_segment.end() as uint)
}
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
#[feature(macro_registrar, managed_boxes)];
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::cmp;
+use std::vec_ng::Vec;
+
+#[deriving(Show, Clone)]
+pub struct LogDirective {
+ name: Option<~str>,
+ level: u32,
+}
+
+static LOG_LEVEL_NAMES: [&'static str, ..4] = ["error", "warn", "info",
+ "debug"];
+
+/// Parse an individual log level that is either a number or a symbolic log level
+fn parse_log_level(level: &str) -> Option<u32> {
+ from_str::<u32>(level).or_else(|| {
+ let pos = LOG_LEVEL_NAMES.iter().position(|&name| name == level);
+ pos.map(|p| p as u32 + 1)
+ }).map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
+}
+
+/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1")
+/// and return a vector with log directives.
+///
+/// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in
+/// std::). Also supports string log levels of error, warn, info, and debug
+pub fn parse_logging_spec(spec: &str) -> Vec<LogDirective> {
+ let mut dirs = Vec::new();
+ for s in spec.split(',') {
+ if s.len() == 0 { continue }
+ let mut parts = s.split('=');
+ let (log_level, name) = match (parts.next(), parts.next(), parts.next()) {
+ (Some(part0), None, None) => {
+ // if the single argument is a log-level string or number,
+ // treat that as a global fallback
+ match parse_log_level(part0) {
+ Some(num) => (num, None),
+ None => (::MAX_LOG_LEVEL, Some(part0)),
+ }
+ }
+ (Some(part0), Some(part1), None) => {
+ match parse_log_level(part1) {
+ Some(num) => (num, Some(part0)),
+ _ => {
+ println!("warning: invalid logging spec '{}', \
+ ignoring it", part1);
+ continue
+ }
+ }
+ },
+ _ => {
+ println!("warning: invalid logging spec '{}', \
+ ignoring it", s);
+ continue
+ }
+ };
+ dirs.push(LogDirective {
+ name: name.map(|s| s.to_owned()),
+ level: log_level,
+ });
+ }
+ return dirs;
+}
+
+#[cfg(test)]
+mod tests {
+ use super::parse_logging_spec;
+
+ #[test]
+ fn parse_logging_spec_valid() {
+ let dirs = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4");
+ let dirs = dirs.as_slice();
+ assert_eq!(dirs.len(), 3);
+ assert_eq!(dirs[0].name, Some(~"crate1::mod1"));
+ assert_eq!(dirs[0].level, 1);
+
+ assert_eq!(dirs[1].name, Some(~"crate1::mod2"));
+ assert_eq!(dirs[1].level, ::MAX_LOG_LEVEL);
+
+ assert_eq!(dirs[2].name, Some(~"crate2"));
+ assert_eq!(dirs[2].level, 4);
+ }
+
+ #[test]
+ fn parse_logging_spec_invalid_crate() {
+ // test parse_logging_spec with multiple = in specification
+ let dirs = parse_logging_spec("crate1::mod1=1=2,crate2=4");
+ let dirs = dirs.as_slice();
+ assert_eq!(dirs.len(), 1);
+ assert_eq!(dirs[0].name, Some(~"crate2"));
+ assert_eq!(dirs[0].level, 4);
+ }
+
+ #[test]
+ fn parse_logging_spec_invalid_log_level() {
+ // test parse_logging_spec with 'noNumber' as log level
+ let dirs = parse_logging_spec("crate1::mod1=noNumber,crate2=4");
+ let dirs = dirs.as_slice();
+ assert_eq!(dirs.len(), 1);
+ assert_eq!(dirs[0].name, Some(~"crate2"));
+ assert_eq!(dirs[0].level, 4);
+ }
+
+ #[test]
+ fn parse_logging_spec_string_log_level() {
+ // test parse_logging_spec with 'warn' as log level
+ let dirs = parse_logging_spec("crate1::mod1=wrong,crate2=warn");
+ let dirs = dirs.as_slice();
+ assert_eq!(dirs.len(), 1);
+ assert_eq!(dirs[0].name, Some(~"crate2"));
+ assert_eq!(dirs[0].level, ::WARN);
+ }
+
+ #[test]
+ fn parse_logging_spec_global() {
+ // test parse_logging_spec with no crate
+ let dirs = parse_logging_spec("warn,crate2=4");
+ let dirs = dirs.as_slice();
+ assert_eq!(dirs.len(), 2);
+ assert_eq!(dirs[0].name, None);
+ assert_eq!(dirs[0].level, 2);
+ assert_eq!(dirs[1].name, Some(~"crate2"));
+ assert_eq!(dirs[1].level, 4);
+ }
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+Utilities for program-wide and customizable logging
+
+## Example
+
+```
+#[feature(phase)];
+#[phase(syntax, link)] extern crate log;
+
+fn main() {
+ debug!("this is a debug {}", "message");
+ error!("this is printed by default");
+
+ if log_enabled!(log::INFO) {
+ let x = 3 * 4; // expensive computation
+ info!("the answer was: {}", x);
+ }
+}
+```
+
+## Logging Macros
+
+There are five macros that the logging subsystem uses:
+
+* `log!(level, ...)` - the generic logging macro, takes a level as a u32 and any
+ related `format!` arguments
+* `debug!(...)` - a macro hard-wired to the log level of `DEBUG`
+* `info!(...)` - a macro hard-wired to the log level of `INFO`
+* `warn!(...)` - a macro hard-wired to the log level of `WARN`
+* `error!(...)` - a macro hard-wired to the log level of `ERROR`
+
+All of these macros use std::the same style of syntax as the `format!` syntax
+extension. Details about the syntax can be found in the documentation of
+`std::fmt` along with the Rust tutorial/manual.
+
+If you want to check at runtime if a given logging level is enabled (e.g. if the
+information you would want to log is expensive to produce), you can use std::the
+following macro:
+
+* `log_enabled!(level)` - returns true if logging of the given level is enabled
+
+## Enabling logging
+
+Log levels are controlled on a per-module basis, and by default all logging is
+disabled except for `error!` (a log level of 1). Logging is controlled via the
+`RUST_LOG` environment variable. The value of this environment variable is a
+comma-separated list of logging directives. A logging directive is of the form:
+
+```notrust
+path::to::module=log_level
+```
+
+The path to the module is rooted in the name of the crate it was compiled for,
+so if your program is contained in a file `hello.rs`, for example, to turn on
+logging for this file you would use std::a value of `RUST_LOG=hello`.
+Furthermore, this path is a prefix-search, so all modules nested in the
+specified module will also have logging enabled.
+
+The actual `log_level` is optional to specify. If omitted, all logging will be
+enabled. If specified, the it must be either a numeric in the range of 1-255, or
+it must be one of the strings `debug`, `error`, `info`, or `warn`. If a numeric
+is specified, then all logging less than or equal to that numeral is enabled.
+For example, if logging level 3 is active, error, warn, and info logs will be
+printed, but debug will be omitted.
+
+As the log level for a module is optional, the module to enable logging for is
+also optional. If only a `log_level` is provided, then the global log level for
+all modules is set to this value.
+
+Some examples of valid values of `RUST_LOG` are:
+
+```notrust
+hello // turns on all logging for the 'hello' module
+info // turns on all info logging
+hello=debug // turns on debug logging for 'hello'
+hello=3 // turns on info logging for 'hello'
+hello,std::option // turns on hello, and std's option logging
+error,hello=warn // turn on global error logging and also warn for hello
+```
+
+## Performance and Side Effects
+
+Each of these macros will expand to code similar to:
+
+```rust,ignore
+if log_level <= my_module_log_level() {
+ ::log::log(log_level, format!(...));
+}
+```
+
+What this means is that each of these macros are very cheap at runtime if
+they're turned off (just a load and an integer comparison). This also means that
+if logging is disabled, none of the components of the log will be executed.
+
+*/
+
+#[crate_id = "log#0.10-pre"];
+#[license = "MIT/ASL2"];
+#[crate_type = "rlib"];
+#[crate_type = "dylib"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
+
+#[feature(macro_rules)];
+#[deny(missing_doc)];
+
+extern crate sync;
+
+use std::cast;
+use std::fmt;
+use std::io::LineBufferedWriter;
+use std::io;
+use std::local_data;
+use std::os;
+use std::rt;
+use std::vec;
+use std::vec_ng::Vec;
+
+use sync::one::{Once, ONCE_INIT};
+
+pub mod macros;
+mod directive;
+
+/// Maximum logging level of a module that can be specified. Common logging
+/// levels are found in the DEBUG/INFO/WARN/ERROR constants.
+pub static MAX_LOG_LEVEL: u32 = 255;
+
+/// The default logging level of a crate if no other is specified.
+static DEFAULT_LOG_LEVEL: u32 = 1;
+
+/// An unsafe constant that is the maximum logging level of any module
+/// specified. This is the first line of defense to determining whether a
+/// logging statement should be run.
+static mut LOG_LEVEL: u32 = MAX_LOG_LEVEL;
+
+static mut DIRECTIVES: *Vec<directive::LogDirective> =
+ 0 as *Vec<directive::LogDirective>;
+
+/// Debug log level
+pub static DEBUG: u32 = 4;
+/// Info log level
+pub static INFO: u32 = 3;
+/// Warn log level
+pub static WARN: u32 = 2;
+/// Error log level
+pub static ERROR: u32 = 1;
+
+local_data_key!(local_logger: ~Logger)
+
+/// A trait used to represent an interface to a task-local logger. Each task
+/// can have its own custom logger which can respond to logging messages
+/// however it likes.
+pub trait Logger {
+ /// Logs a single message described by the `args` structure. The level is
+ /// provided in case you want to do things like color the message, etc.
+ fn log(&mut self, level: u32, args: &fmt::Arguments);
+}
+
+struct DefaultLogger {
+ handle: LineBufferedWriter<io::stdio::StdWriter>,
+}
+
+impl Logger for DefaultLogger {
+ // by default, just ignore the level
+ fn log(&mut self, _level: u32, args: &fmt::Arguments) {
+ match fmt::writeln(&mut self.handle, args) {
+ Err(e) => fail!("failed to log: {}", e),
+ Ok(()) => {}
+ }
+ }
+}
+
+impl Drop for DefaultLogger {
+ fn drop(&mut self) {
+ // FIXME(#12628): is failure the right thing to do?
+ match self.handle.flush() {
+ Err(e) => fail!("failed to flush a logger: {}", e),
+ Ok(()) => {}
+ }
+ }
+}
+
+/// This function is called directly by the compiler when using the logging
+/// macros. This function does not take into account whether the log level
+/// specified is active or not, it will always log something if this method is
+/// called.
+///
+/// It is not recommended to call this function directly, rather it should be
+/// invoked through the logging family of macros.
+pub fn log(level: u32, args: &fmt::Arguments) {
+ // Completely remove the local logger from TLS in case anyone attempts to
+ // frob the slot while we're doing the logging. This will destroy any logger
+ // set during logging.
+ let mut logger = local_data::pop(local_logger).unwrap_or_else(|| {
+ ~DefaultLogger { handle: io::stderr() } as ~Logger
+ });
+ logger.log(level, args);
+ local_data::set(local_logger, logger);
+}
+
+/// Getter for the global log level. This is a function so that it can be called
+/// safely
+#[doc(hidden)]
+#[inline(always)]
+pub fn log_level() -> u32 { unsafe { LOG_LEVEL } }
+
+/// Replaces the task-local logger with the specified logger, returning the old
+/// logger.
+pub fn set_logger(logger: ~Logger) -> Option<~Logger> {
+ let prev = local_data::pop(local_logger);
+ local_data::set(local_logger, logger);
+ return prev;
+}
+
+/// Tests whether a given module's name is enabled for a particular level of
+/// logging. This is the second layer of defense about determining whether a
+/// module's log statement should be emitted or not.
+#[doc(hidden)]
+pub fn mod_enabled(level: u32, module: &str) -> bool {
+ static mut INIT: Once = ONCE_INIT;
+ unsafe { INIT.doit(init); }
+
+ // It's possible for many threads are in this function, only one of them
+ // will peform the global initialization, but all of them will need to check
+ // again to whether they should really be here or not. Hence, despite this
+ // check being expanded manually in the logging macro, this function checks
+ // the log level again.
+ if level > unsafe { LOG_LEVEL } { return false }
+
+ // This assertion should never get tripped unless we're in an at_exit
+ // handler after logging has been torn down and a logging attempt was made.
+ assert!(unsafe { !DIRECTIVES.is_null() });
+
+ enabled(level, module, unsafe { (*DIRECTIVES).iter() })
+}
+
+fn enabled(level: u32, module: &str,
+ iter: vec::Items<directive::LogDirective>) -> bool {
+ // Search for the longest match, the vector is assumed to be pre-sorted.
+ for directive in iter.rev() {
+ match directive.name {
+ Some(ref name) if !module.starts_with(*name) => {},
+ Some(..) | None => {
+ return level <= directive.level
+ }
+ }
+ }
+ level <= DEFAULT_LOG_LEVEL
+}
+
+/// Initialize logging for the current process.
+///
+/// This is not threadsafe at all, so initialization os performed through a
+/// `Once` primitive (and this function is called from that primitive).
+fn init() {
+ let mut directives = match os::getenv("RUST_LOG") {
+ Some(spec) => directive::parse_logging_spec(spec),
+ None => Vec::new(),
+ };
+
+ // Sort the provided directives by length of their name, this allows a
+ // little more efficient lookup at runtime.
+ directives.sort_by(|a, b| {
+ let alen = a.name.as_ref().map(|a| a.len()).unwrap_or(0);
+ let blen = b.name.as_ref().map(|b| b.len()).unwrap_or(0);
+ alen.cmp(&blen)
+ });
+
+ let max_level = {
+ let max = directives.iter().max_by(|d| d.level);
+ max.map(|d| d.level).unwrap_or(DEFAULT_LOG_LEVEL)
+ };
+
+ unsafe {
+ LOG_LEVEL = max_level;
+
+ assert!(DIRECTIVES.is_null());
+ DIRECTIVES = cast::transmute(~directives);
+
+ // Schedule the cleanup for this global for when the runtime exits.
+ rt::at_exit(proc() {
+ assert!(!DIRECTIVES.is_null());
+ let _directives: ~Vec<directive::LogDirective> =
+ cast::transmute(DIRECTIVES);
+ DIRECTIVES = 0 as *Vec<directive::LogDirective>;
+ });
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::enabled;
+ use directive::LogDirective;
+
+ #[test]
+ fn match_full_path() {
+ let dirs = [LogDirective { name: Some(~"crate2"), level: 3 },
+ LogDirective { name: Some(~"crate1::mod1"), level: 2 }];
+ assert!(enabled(2, "crate1::mod1", dirs.iter()));
+ assert!(!enabled(3, "crate1::mod1", dirs.iter()));
+ assert!(enabled(3, "crate2", dirs.iter()));
+ assert!(!enabled(4, "crate2", dirs.iter()));
+ }
+
+ #[test]
+ fn no_match() {
+ let dirs = [LogDirective { name: Some(~"crate2"), level: 3 },
+ LogDirective { name: Some(~"crate1::mod1"), level: 2 }];
+ assert!(!enabled(2, "crate3", dirs.iter()));
+ }
+
+ #[test]
+ fn match_beginning() {
+ let dirs = [LogDirective { name: Some(~"crate2"), level: 3 },
+ LogDirective { name: Some(~"crate1::mod1"), level: 2 }];
+ assert!(enabled(3, "crate2::mod1", dirs.iter()));
+ }
+
+ #[test]
+ fn match_beginning_longest_match() {
+ let dirs = [LogDirective { name: Some(~"crate2"), level: 3 },
+ LogDirective { name: Some(~"crate2::mod"), level: 4 },
+ LogDirective { name: Some(~"crate1::mod1"), level: 2 }];
+ assert!(enabled(4, "crate2::mod1", dirs.iter()));
+ assert!(!enabled(4, "crate2", dirs.iter()));
+ }
+
+ #[test]
+ fn match_default() {
+ let dirs = [LogDirective { name: None, level: 3 },
+ LogDirective { name: Some(~"crate1::mod1"), level: 2 }];
+ assert!(enabled(2, "crate1::mod1", dirs.iter()));
+ assert!(enabled(3, "crate2::mod2", dirs.iter()));
+ }
+
+ #[test]
+ fn zero_level() {
+ let dirs = [LogDirective { name: None, level: 3 },
+ LogDirective { name: Some(~"crate1::mod1"), level: 0 }];
+ assert!(!enabled(1, "crate1::mod1", dirs.iter()));
+ assert!(enabled(3, "crate2::mod2", dirs.iter()));
+ }
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Logging macros
+
+#[macro_escape];
+
+/// The standard logging macro
+///
+/// This macro will generically log over a provided level (of type u32) with a
+/// format!-based argument list. See documentation in `std::fmt` for details on
+/// how to use the syntax.
+///
+/// # Example
+///
+/// ```
+/// #[feature(phase)];
+/// #[phase(syntax, link)] extern crate log;
+///
+/// # fn main() {
+/// log!(log::DEBUG, "this is a debug message");
+/// log!(log::WARN, "this is a warning {}", "message");
+/// log!(6, "this is a custom logging level: {level}", level=6);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! log(
+ ($lvl:expr, $($arg:tt)+) => ({
+ let lvl = $lvl;
+ if log_enabled!(lvl) {
+ format_args!(|args| { ::log::log(lvl, args) }, $($arg)+)
+ }
+ })
+)
+
+/// A convenience macro for logging at the error log level.
+///
+/// # Example
+///
+/// ```
+/// #[feature(phase)];
+/// #[phase(syntax, link)] extern crate log;
+///
+/// # fn main() {
+/// # let error = 3;
+/// error!("the build has failed with error code: {}", error);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! error(
+ ($($arg:tt)*) => (log!(::log::ERROR, $($arg)*))
+)
+
+/// A convenience macro for logging at the warning log level.
+///
+/// # Example
+///
+/// ```
+/// #[feature(phase)];
+/// #[phase(syntax, link)] extern crate log;
+///
+/// # fn main() {
+/// # let code = 3;
+/// warn!("you may like to know that a process exited with: {}", code);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! warn(
+ ($($arg:tt)*) => (log!(::log::WARN, $($arg)*))
+)
+
+/// A convenience macro for logging at the info log level.
+///
+/// # Example
+///
+/// ```
+/// #[feature(phase)];
+/// #[phase(syntax, link)] extern crate log;
+///
+/// # fn main() {
+/// # let ret = 3;
+/// info!("this function is about to return: {}", ret);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! info(
+ ($($arg:tt)*) => (log!(::log::INFO, $($arg)*))
+)
+
+/// A convenience macro for logging at the debug log level. This macro can also
+/// be omitted at compile time by passing `--cfg ndebug` to the compiler. If
+/// this option is not passed, then debug statements will be compiled.
+///
+/// # Example
+///
+/// ```
+/// #[feature(phase)];
+/// #[phase(syntax, link)] extern crate log;
+///
+/// # fn main() {
+/// debug!("x = {x}, y = {y}", x=10, y=20);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! debug(
+ ($($arg:tt)*) => (if cfg!(not(ndebug)) { log!(::log::DEBUG, $($arg)*) })
+)
+
+/// A macro to test whether a log level is enabled for the current module.
+///
+/// # Example
+///
+/// ```
+/// #[feature(phase)];
+/// #[phase(syntax, link)] extern crate log;
+///
+/// # fn main() {
+/// # struct Point { x: int, y: int }
+/// # fn some_expensive_computation() -> Point { Point { x: 1, y: 2 } }
+/// if log_enabled!(log::DEBUG) {
+/// let x = some_expensive_computation();
+/// debug!("x.x = {}, x.y = {}", x.x, x.y);
+/// }
+/// # }
+/// ```
+#[macro_export]
+macro_rules! log_enabled(
+ ($lvl:expr) => ({
+ let lvl = $lvl;
+ (lvl != ::log::DEBUG || cfg!(not(ndebug))) &&
+ lvl <= ::log::log_level() &&
+ ::log::mod_enabled(lvl, module_path!())
+ })
+)
if self.close_on_drop && self.fd > libc::STDERR_FILENO {
let n = unsafe { libc::close(self.fd) };
if n != 0 {
- warn!("error {} when closing file descriptor {}", n, self.fd);
+ println!("error {} when closing file descriptor {}", n,
+ self.fd);
}
}
}
let mut buf = Vec::<u8>::with_capacity(size as uint);
let ptr = buf.as_mut_slice().as_mut_ptr() as *mut dirent_t;
- debug!("os::list_dir -- BEFORE OPENDIR");
-
let dir_ptr = p.with_ref(|buf| unsafe { opendir(buf) });
if dir_ptr as uint != 0 {
let mut paths = ~[];
- debug!("os::list_dir -- opendir() SUCCESS");
let mut entry_ptr = 0 as *mut dirent_t;
while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } {
if entry_ptr.is_null() { break }
if self.close_on_drop && self.fd > libc::STDERR_FILENO {
let n = unsafe { libc::close(self.fd) };
if n != 0 {
- warn!("error {} when closing file descriptor {}", n, self.fd);
+ println!("error {} when closing file descriptor {}", n, self.fd);
}
}
}
libc::ERROR_INVALID_FUNCTION => (io::InvalidInput,
"illegal operation on a directory"),
- x => {
- debug!("ignoring {}: {}", x, os::last_os_error());
- (io::OtherIoError, "unknown error")
- }
+ _ => (io::OtherIoError, "unknown error")
}
}
x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
(io::ResourceUnavailable, "resource temporarily unavailable"),
- x => {
- debug!("ignoring {}: {}", x, os::last_os_error());
- (io::OtherIoError, "unknown error")
- }
+ _ => (io::OtherIoError, "unknown error")
}
}
fn clone(&self) -> ~rtio::RtioTcpStream {
~TcpStream { inner: self.inner.clone() } as ~rtio::RtioTcpStream
}
+ fn close_write(&mut self) -> IoResult<()> {
+ super::mkerr_libc(unsafe {
+ libc::shutdown(self.fd(), libc::SHUT_WR)
+ })
+ }
}
impl rtio::RtioSocket for TcpStream {
};
let mut incoming = false;
- debug!("{} events to process", n);
for event in events.slice_to(n as uint).iter() {
let fd = event.data as libc::c_int;
- debug!("data on fd {} (input = {})", fd, input);
if fd == input {
let mut buf = [0, ..1];
// drain the input file descriptor of its input
html_root_url = "http://static.rust-lang.org/doc/master")];
#[deny(unused_result, unused_must_use)];
#[allow(non_camel_case_types)];
+#[allow(deprecated_owned_vector)];
// NB this crate explicitly does *not* allow glob imports, please seriously
// consider whether they're needed before adding that feature here (the
pub fn spawn_opts(opts: TaskOpts, f: proc()) {
let TaskOpts {
notify_chan, name, stack_size,
- logger, stderr, stdout,
+ stderr, stdout,
} = opts;
let mut task = ~Task::new();
task.name = name;
- task.logger = logger;
task.stderr = stderr;
task.stdout = stdout;
match notify_chan {
use rand::Rng;
use std::str;
use std::uint;
-use std::vec;
use std::{i64, u64};
+use std::vec_ng;
+use std::vec_ng::Vec;
/**
A `BigDigit` is a `BigUint`'s composing element.
pub type BigDigit = u32;
pub static ZERO_BIG_DIGIT: BigDigit = 0;
+static ZERO_VEC: [BigDigit, ..1] = [ZERO_BIG_DIGIT];
pub mod BigDigit {
use super::BigDigit;
*/
#[deriving(Clone)]
pub struct BigUint {
- priv data: ~[BigDigit]
+ priv data: Vec<BigDigit>
}
impl Eq for BigUint {
impl BitAnd<BigUint, BigUint> for BigUint {
fn bitand(&self, other: &BigUint) -> BigUint {
- let new_len = cmp::min(self.data.len(), other.data.len());
- let anded = vec::from_fn(new_len, |i| {
- // i will never be less than the size of either data vector
- let ai = self.data[i];
- let bi = other.data[i];
- ai & bi
- });
- return BigUint::new(anded);
+ BigUint::new(self.data.iter().zip(other.data.iter()).map(|(ai, bi)| *ai & *bi).collect())
}
}
impl BitOr<BigUint, BigUint> for BigUint {
fn bitor(&self, other: &BigUint) -> BigUint {
- let new_len = cmp::max(self.data.len(), other.data.len());
- let ored = vec::from_fn(new_len, |i| {
- let ai = if i < self.data.len() { self.data[i] } else { 0 };
- let bi = if i < other.data.len() { other.data[i] } else { 0 };
- ai | bi
- });
+ let zeros = ZERO_VEC.iter().cycle();
+ let (a, b) = if self.data.len() > other.data.len() { (self, other) } else { (other, self) };
+ let ored = a.data.iter().zip(b.data.iter().chain(zeros)).map(
+ |(ai, bi)| *ai | *bi
+ ).collect();
return BigUint::new(ored);
}
}
impl BitXor<BigUint, BigUint> for BigUint {
fn bitxor(&self, other: &BigUint) -> BigUint {
- let new_len = cmp::max(self.data.len(), other.data.len());
- let xored = vec::from_fn(new_len, |i| {
- let ai = if i < self.data.len() { self.data[i] } else { 0 };
- let bi = if i < other.data.len() { other.data[i] } else { 0 };
- ai ^ bi
- });
+ let zeros = ZERO_VEC.iter().cycle();
+ let (a, b) = if self.data.len() > other.data.len() { (self, other) } else { (other, self) };
+ let xored = a.data.iter().zip(b.data.iter().chain(zeros)).map(
+ |(ai, bi)| *ai ^ *bi
+ ).collect();
return BigUint::new(xored);
}
}
impl Zero for BigUint {
#[inline]
- fn zero() -> BigUint { BigUint::new(~[]) }
+ fn zero() -> BigUint { BigUint::new(Vec::new()) }
#[inline]
fn is_zero(&self) -> bool { self.data.is_empty() }
impl One for BigUint {
#[inline]
- fn one() -> BigUint { BigUint::new(~[1]) }
+ fn one() -> BigUint { BigUint::new(vec!(1)) }
}
impl Unsigned for BigUint {}
impl Add<BigUint, BigUint> for BigUint {
fn add(&self, other: &BigUint) -> BigUint {
- let new_len = cmp::max(self.data.len(), other.data.len());
+ let zeros = ZERO_VEC.iter().cycle();
+ let (a, b) = if self.data.len() > other.data.len() { (self, other) } else { (other, self) };
let mut carry = 0;
- let mut sum = vec::from_fn(new_len, |i| {
- let ai = if i < self.data.len() { self.data[i] } else { 0 };
- let bi = if i < other.data.len() { other.data[i] } else { 0 };
- let (hi, lo) = BigDigit::from_uint(
- (ai as uint) + (bi as uint) + (carry as uint)
- );
+ let mut sum: Vec<BigDigit> = a.data.iter().zip(b.data.iter().chain(zeros)).map(|(ai, bi)| {
+ let (hi, lo) = BigDigit::from_uint((*ai as uint) + (*bi as uint) + (carry as uint));
carry = hi;
lo
- });
+ }).collect();
if carry != 0 { sum.push(carry); }
return BigUint::new(sum);
}
impl Sub<BigUint, BigUint> for BigUint {
fn sub(&self, other: &BigUint) -> BigUint {
let new_len = cmp::max(self.data.len(), other.data.len());
+ let zeros = ZERO_VEC.iter().cycle();
+ let (a, b) = (self.data.iter().chain(zeros.clone()), other.data.iter().chain(zeros));
let mut borrow = 0;
- let diff = vec::from_fn(new_len, |i| {
- let ai = if i < self.data.len() { self.data[i] } else { 0 };
- let bi = if i < other.data.len() { other.data[i] } else { 0 };
+ let diff: Vec<BigDigit> = a.take(new_len).zip(b).map(|(ai, bi)| {
let (hi, lo) = BigDigit::from_uint(
- (BigDigit::base) +
- (ai as uint) - (bi as uint) - (borrow as uint)
+ BigDigit::base + (*ai as uint) - (*bi as uint) - (borrow as uint)
);
/*
hi * (base) + lo == 1*(base) + ai - bi - borrow
*/
borrow = if hi == 0 { 1 } else { 0 };
lo
- });
+ }).collect();
assert_eq!(borrow, 0); // <=> assert!((self >= other));
return BigUint::new(diff);
if self.is_zero() || other.is_zero() { return Zero::zero(); }
let (s_len, o_len) = (self.data.len(), other.data.len());
- if s_len == 1 { return mul_digit(other, self.data[0]); }
- if o_len == 1 { return mul_digit(self, other.data[0]); }
+ if s_len == 1 { return mul_digit(other, self.data.as_slice()[0]); }
+ if o_len == 1 { return mul_digit(self, other.data.as_slice()[0]); }
// Using Karatsuba multiplication
// (a1 * base + a0) * (b1 * base + b0)
if n == 1 { return (*a).clone(); }
let mut carry = 0;
- let mut prod = a.data.iter().map(|ai| {
+ let mut prod: Vec<BigDigit> = a.data.iter().map(|ai| {
let (hi, lo) = BigDigit::from_uint(
(*ai as uint) * (n as uint) + (carry as uint)
);
carry = hi;
lo
- }).collect::<~[BigDigit]>();
+ }).collect();
if carry != 0 { prod.push(carry); }
return BigUint::new(prod);
}
return (Zero::zero(), Zero::zero(), (*a).clone());
}
- let an = a.data.slice(a.data.len() - n, a.data.len());
+ let an = a.data.tailn(a.data.len() - n);
let bn = *b.data.last().unwrap();
- let mut d = ~[];
+ let mut d = Vec::with_capacity(an.len());
let mut carry = 0;
for elt in an.rev_iter() {
let ai = BigDigit::to_uint(carry, *elt);
let di = ai / (bn as uint);
assert!(di < BigDigit::base);
carry = (ai % (bn as uint)) as BigDigit;
- d = ~[di as BigDigit] + d;
+ d.push(di as BigDigit)
}
+ d.reverse();
let shift = (a.data.len() - an.len()) - (b.data.len() - 1);
if shift == 0 {
return (BigUint::new(d), One::one(), (*b).clone());
}
let one: BigUint = One::one();
- return (BigUint::from_slice(d).shl_unit(shift),
+ return (BigUint::new(d).shl_unit(shift),
one.shl_unit(shift),
b.shl_unit(shift));
}
#[inline]
fn is_even(&self) -> bool {
// Considering only the last digit.
- if self.data.is_empty() {
- true
- } else {
- self.data[0].is_even()
+ match self.data.as_slice().head() {
+ Some(x) => x.is_even(),
+ None => true
}
}
fn to_u64(&self) -> Option<u64> {
match self.data.len() {
0 => Some(0),
- 1 => Some(self.data[0] as u64),
+ 1 => Some(self.data.as_slice()[0] as u64),
2 => {
- Some(BigDigit::to_uint(self.data[1], self.data[0]) as u64)
+ Some(BigDigit::to_uint(self.data.as_slice()[1], self.data.as_slice()[0]) as u64)
}
3 => {
- let n_lo = BigDigit::to_uint(self.data[1], self.data[0]) as
+ let n_lo = BigDigit::to_uint(self.data.as_slice()[1], self.data.as_slice()[0]) as
u64;
- let n_hi = self.data[2] as u64;
+ let n_hi = self.data.as_slice()[2] as u64;
Some((n_hi << 32) + n_lo)
}
4 => {
- let n_lo = BigDigit::to_uint(self.data[1], self.data[0])
+ let n_lo = BigDigit::to_uint(self.data.as_slice()[1], self.data.as_slice()[0])
as u64;
- let n_hi = BigDigit::to_uint(self.data[3], self.data[2])
+ let n_hi = BigDigit::to_uint(self.data.as_slice()[3], self.data.as_slice()[2])
as u64;
Some((n_hi << 32) + n_lo)
}
fn to_u64(&self) -> Option<u64> {
match self.data.len() {
0 => Some(0),
- 1 => Some(self.data[0] as u64),
- 2 => Some(BigDigit::to_uint(self.data[1], self.data[0]) as u64),
+ 1 => Some(self.data.as_slice()[0] as u64),
+ 2 => Some(BigDigit::to_uint(self.data.as_slice()[1], self.data.as_slice()[0]) as u64),
_ => None
}
}
let n = match (BigDigit::from_uint(n_hi), BigDigit::from_uint(n_lo)) {
((0, 0), (0, 0)) => Zero::zero(),
- ((0, 0), (0, n0)) => BigUint::new(~[n0]),
- ((0, 0), (n1, n0)) => BigUint::new(~[n0, n1]),
- ((0, n2), (n1, n0)) => BigUint::new(~[n0, n1, n2]),
- ((n3, n2), (n1, n0)) => BigUint::new(~[n0, n1, n2, n3]),
+ ((0, 0), (0, n0)) => BigUint::new(vec!(n0)),
+ ((0, 0), (n1, n0)) => BigUint::new(vec!(n0, n1)),
+ ((0, n2), (n1, n0)) => BigUint::new(vec!(n0, n1, n2)),
+ ((n3, n2), (n1, n0)) => BigUint::new(vec!(n0, n1, n2, n3)),
};
Some(n)
}
fn from_u64(n: u64) -> Option<BigUint> {
let n = match BigDigit::from_uint(n as uint) {
(0, 0) => Zero::zero(),
- (0, n0) => BigUint::new(~[n0]),
- (n1, n0) => BigUint::new(~[n0, n1])
+ (0, n0) => BigUint::new(vec!(n0)),
+ (n1, n0) => BigUint::new(vec!(n0, n1))
};
Some(n)
}
assert!(1 < radix && radix <= 16);
let (base, max_len) = get_radix_base(radix);
if base == BigDigit::base {
- return fill_concat(self.data, radix, max_len)
+ return fill_concat(self.data.as_slice(), radix, max_len)
}
- return fill_concat(convert_base((*self).clone(), base), radix, max_len);
+ return fill_concat(convert_base(self, base).as_slice(), radix, max_len);
- fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] {
+ fn convert_base(n: &BigUint, base: uint) -> Vec<BigDigit> {
let divider = FromPrimitive::from_uint(base).unwrap();
- let mut result = ~[];
- let mut m = n;
+ let mut result = Vec::new();
+ let mut m = n.clone();
while m >= divider {
let (d, m0) = m.div_mod_floor(÷r);
result.push(m0.to_uint().unwrap() as BigDigit);
impl BigUint {
/// Creates and initializes a `BigUint`.
#[inline]
- pub fn new(v: ~[BigDigit]) -> BigUint {
+ pub fn new(v: Vec<BigDigit>) -> BigUint {
// omit trailing zeros
let new_len = v.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1);
/// Creates and initializes a `BigUint`.
#[inline]
pub fn from_slice(slice: &[BigDigit]) -> BigUint {
- return BigUint::new(slice.to_owned());
+ return BigUint::new(Vec::from_slice(slice));
}
/// Creates and initializes a `BigUint`.
fn shl_unit(&self, n_unit: uint) -> BigUint {
if n_unit == 0 || self.is_zero() { return (*self).clone(); }
- return BigUint::new(vec::from_elem(n_unit, ZERO_BIG_DIGIT)
- + self.data);
+ return BigUint::new(vec_ng::append(Vec::from_elem(n_unit, ZERO_BIG_DIGIT),
+ self.data.as_slice()));
}
#[inline]
if n_bits == 0 || self.is_zero() { return (*self).clone(); }
let mut carry = 0;
- let mut shifted = self.data.iter().map(|elem| {
+ let mut shifted: Vec<BigDigit> = self.data.iter().map(|elem| {
let (hi, lo) = BigDigit::from_uint(
(*elem as uint) << n_bits | (carry as uint)
);
carry = hi;
lo
- }).collect::<~[BigDigit]>();
+ }).collect();
if carry != 0 { shifted.push(carry); }
return BigUint::new(shifted);
}
if n_bits == 0 || self.data.is_empty() { return (*self).clone(); }
let mut borrow = 0;
- let mut shifted_rev = vec::with_capacity(self.data.len());
+ let mut shifted_rev = Vec::with_capacity(self.data.len());
for elem in self.data.rev_iter() {
shifted_rev.push((*elem >> n_bits) | borrow);
borrow = *elem << (BigDigit::bits - n_bits);
impl<R: Rng> RandBigInt for R {
fn gen_biguint(&mut self, bit_size: uint) -> BigUint {
let (digits, rem) = bit_size.div_rem(&BigDigit::bits);
- let mut data = vec::with_capacity(digits+1);
+ let mut data = Vec::with_capacity(digits+1);
for _ in range(0, digits) {
data.push(self.gen());
}
impl BigInt {
/// Creates and initializes a BigInt.
#[inline]
- pub fn new(sign: Sign, v: ~[BigDigit]) -> BigInt {
+ pub fn new(sign: Sign, v: Vec<BigDigit>) -> BigInt {
BigInt::from_biguint(sign, BigUint::new(v))
}
use std::num::{ToPrimitive, FromPrimitive};
use std::num::CheckedDiv;
use rand::{task_rng};
- use std::str;
use std::u64;
- use std::vec;
+ use std::vec_ng::Vec;
#[test]
fn test_from_slice() {
fn check(slice: &[BigDigit], data: &[BigDigit]) {
- assert!(data == BigUint::from_slice(slice).data);
+ assert!(data == BigUint::from_slice(slice).data.as_slice());
}
check([1], [1]);
check([0, 0, 0], []);
#[test]
fn test_cmp() {
- let data: ~[BigUint] = [ &[], &[1], &[2], &[-1], &[0, 1], &[2, 1], &[1, 1, 1] ]
- .map(|v| BigUint::from_slice(*v));
+ let data: Vec<BigUint> = [ &[], &[1], &[2], &[-1], &[0, 1], &[2, 1], &[1, 1, 1] ]
+ .iter().map(|v| BigUint::from_slice(*v)).collect();
for (i, ni) in data.iter().enumerate() {
for (j0, nj) in data.slice(i, data.len()).iter().enumerate() {
let j = j0 + i;
#[test]
fn test_bitand() {
- fn check(left: ~[BigDigit],
- right: ~[BigDigit],
- expected: ~[BigDigit]) {
- assert_eq!(BigUint::new(left) & BigUint::new(right),
- BigUint::new(expected));
+ fn check(left: &[BigDigit],
+ right: &[BigDigit],
+ expected: &[BigDigit]) {
+ assert_eq!(BigUint::from_slice(left) & BigUint::from_slice(right),
+ BigUint::from_slice(expected));
}
- check(~[], ~[], ~[]);
- check(~[268, 482, 17],
- ~[964, 54],
- ~[260, 34]);
+ check([], [], []);
+ check([268, 482, 17],
+ [964, 54],
+ [260, 34]);
}
#[test]
fn test_bitor() {
- fn check(left: ~[BigDigit],
- right: ~[BigDigit],
- expected: ~[BigDigit]) {
- assert_eq!(BigUint::new(left) | BigUint::new(right),
- BigUint::new(expected));
+ fn check(left: &[BigDigit],
+ right: &[BigDigit],
+ expected: &[BigDigit]) {
+ assert_eq!(BigUint::from_slice(left) | BigUint::from_slice(right),
+ BigUint::from_slice(expected));
}
- check(~[], ~[], ~[]);
- check(~[268, 482, 17],
- ~[964, 54],
- ~[972, 502, 17]);
+ check([], [], []);
+ check([268, 482, 17],
+ [964, 54],
+ [972, 502, 17]);
}
#[test]
fn test_bitxor() {
- fn check(left: ~[BigDigit],
- right: ~[BigDigit],
- expected: ~[BigDigit]) {
- assert_eq!(BigUint::new(left) ^ BigUint::new(right),
- BigUint::new(expected));
+ fn check(left: &[BigDigit],
+ right: &[BigDigit],
+ expected: &[BigDigit]) {
+ assert_eq!(BigUint::from_slice(left) ^ BigUint::from_slice(right),
+ BigUint::from_slice(expected));
}
- check(~[], ~[], ~[]);
- check(~[268, 482, 17],
- ~[964, 54],
- ~[712, 468, 17]);
+ check([], [], []);
+ check([268, 482, 17],
+ [964, 54],
+ [712, 468, 17]);
}
#[test]
check(One::one(), 1);
check(i64::MAX.to_biguint().unwrap(), i64::MAX);
- check(BigUint::new(~[ ]), 0);
- check(BigUint::new(~[ 1 ]), (1 << (0*BigDigit::bits)));
- check(BigUint::new(~[-1 ]), (1 << (1*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 1 ]), (1 << (1*BigDigit::bits)));
- check(BigUint::new(~[-1, -1 ]), (1 << (2*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 0, 1 ]), (1 << (2*BigDigit::bits)));
- check(BigUint::new(~[-1, -1, -1 ]), (1 << (3*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 0, 0, 1 ]), (1 << (3*BigDigit::bits)));
- check(BigUint::new(~[-1, -1, -1, -1 >> 1]), i64::MAX);
+ check(BigUint::new(vec!( )), 0);
+ check(BigUint::new(vec!( 1 )), (1 << (0*BigDigit::bits)));
+ check(BigUint::new(vec!(-1 )), (1 << (1*BigDigit::bits)) - 1);
+ check(BigUint::new(vec!( 0, 1 )), (1 << (1*BigDigit::bits)));
+ check(BigUint::new(vec!(-1, -1 )), (1 << (2*BigDigit::bits)) - 1);
+ check(BigUint::new(vec!( 0, 0, 1 )), (1 << (2*BigDigit::bits)));
+ check(BigUint::new(vec!(-1, -1, -1 )), (1 << (3*BigDigit::bits)) - 1);
+ check(BigUint::new(vec!( 0, 0, 0, 1 )), (1 << (3*BigDigit::bits)));
+ check(BigUint::new(vec!(-1, -1, -1, -1 >> 1)), i64::MAX);
assert_eq!(i64::MIN.to_biguint(), None);
- assert_eq!(BigUint::new(~[-1, -1, -1, -1 ]).to_i64(), None);
- assert_eq!(BigUint::new(~[ 0, 0, 0, 0, 1]).to_i64(), None);
- assert_eq!(BigUint::new(~[-1, -1, -1, -1, -1]).to_i64(), None);
+ assert_eq!(BigUint::new(vec!(-1, -1, -1, -1 )).to_i64(), None);
+ assert_eq!(BigUint::new(vec!( 0, 0, 0, 0, 1)).to_i64(), None);
+ assert_eq!(BigUint::new(vec!(-1, -1, -1, -1, -1)).to_i64(), None);
}
#[cfg(target_word_size = "64")]
check(One::one(), 1);
check(i64::MAX.to_biguint().unwrap(), i64::MAX);
- check(BigUint::new(~[ ]), 0);
- check(BigUint::new(~[ 1 ]), (1 << (0*BigDigit::bits)));
- check(BigUint::new(~[-1 ]), (1 << (1*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 1 ]), (1 << (1*BigDigit::bits)));
- check(BigUint::new(~[-1, -1 >> 1]), i64::MAX);
+ check(BigUint::new(vec!( )), 0);
+ check(BigUint::new(vec!( 1 )), (1 << (0*BigDigit::bits)));
+ check(BigUint::new(vec!(-1 )), (1 << (1*BigDigit::bits)) - 1);
+ check(BigUint::new(vec!( 0, 1 )), (1 << (1*BigDigit::bits)));
+ check(BigUint::new(vec!(-1, -1 >> 1)), i64::MAX);
assert_eq!(i64::MIN.to_biguint(), None);
- assert_eq!(BigUint::new(~[-1, -1 ]).to_i64(), None);
- assert_eq!(BigUint::new(~[ 0, 0, 1]).to_i64(), None);
- assert_eq!(BigUint::new(~[-1, -1, -1]).to_i64(), None);
+ assert_eq!(BigUint::new(vec!(-1, -1 )).to_i64(), None);
+ assert_eq!(BigUint::new(vec!( 0, 0, 1)).to_i64(), None);
+ assert_eq!(BigUint::new(vec!(-1, -1, -1)).to_i64(), None);
}
#[cfg(target_word_size = "32")]
check(u64::MIN.to_biguint().unwrap(), u64::MIN);
check(u64::MAX.to_biguint().unwrap(), u64::MAX);
- check(BigUint::new(~[ ]), 0);
- check(BigUint::new(~[ 1 ]), (1 << (0*BigDigit::bits)));
- check(BigUint::new(~[-1 ]), (1 << (1*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 1 ]), (1 << (1*BigDigit::bits)));
- check(BigUint::new(~[-1, -1 ]), (1 << (2*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 0, 1 ]), (1 << (2*BigDigit::bits)));
- check(BigUint::new(~[-1, -1, -1 ]), (1 << (3*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 0, 0, 1]), (1 << (3*BigDigit::bits)));
- check(BigUint::new(~[-1, -1, -1, -1]), u64::MAX);
+ check(BigUint::new(vec!( )), 0);
+ check(BigUint::new(vec!( 1 )), (1 << (0*BigDigit::bits)));
+ check(BigUint::new(vec!(-1 )), (1 << (1*BigDigit::bits)) - 1);
+ check(BigUint::new(vec!( 0, 1 )), (1 << (1*BigDigit::bits)));
+ check(BigUint::new(vec!(-1, -1 )), (1 << (2*BigDigit::bits)) - 1);
+ check(BigUint::new(vec!( 0, 0, 1 )), (1 << (2*BigDigit::bits)));
+ check(BigUint::new(vec!(-1, -1, -1 )), (1 << (3*BigDigit::bits)) - 1);
+ check(BigUint::new(vec!( 0, 0, 0, 1)), (1 << (3*BigDigit::bits)));
+ check(BigUint::new(vec!(-1, -1, -1, -1)), u64::MAX);
- assert_eq!(BigUint::new(~[ 0, 0, 0, 0, 1]).to_u64(), None);
- assert_eq!(BigUint::new(~[-1, -1, -1, -1, -1]).to_u64(), None);
+ assert_eq!(BigUint::new(vec!( 0, 0, 0, 0, 1)).to_u64(), None);
+ assert_eq!(BigUint::new(vec!(-1, -1, -1, -1, -1)).to_u64(), None);
}
#[cfg(target_word_size = "64")]
check(u64::MIN.to_biguint().unwrap(), u64::MIN);
check(u64::MAX.to_biguint().unwrap(), u64::MAX);
- check(BigUint::new(~[ ]), 0);
- check(BigUint::new(~[ 1 ]), (1 << (0*BigDigit::bits)));
- check(BigUint::new(~[-1 ]), (1 << (1*BigDigit::bits)) - 1);
- check(BigUint::new(~[ 0, 1]), (1 << (1*BigDigit::bits)));
- check(BigUint::new(~[-1, -1]), u64::MAX);
+ check(BigUint::new(vec!( )), 0);
+ check(BigUint::new(vec!( 1 )), (1 << (0*BigDigit::bits)));
+ check(BigUint::new(vec!(-1 )), (1 << (1*BigDigit::bits)) - 1);
+ check(BigUint::new(vec!( 0, 1)), (1 << (1*BigDigit::bits)));
+ check(BigUint::new(vec!(-1, -1)), u64::MAX);
- assert_eq!(BigUint::new(~[ 0, 0, 1]).to_u64(), None);
- assert_eq!(BigUint::new(~[-1, -1, -1]).to_u64(), None);
+ assert_eq!(BigUint::new(vec!( 0, 0, 1)).to_u64(), None);
+ assert_eq!(BigUint::new(vec!(-1, -1, -1)).to_u64(), None);
}
#[test]
assert_eq!(n.to_bigint().unwrap().to_biguint().unwrap(), n);
}
check(Zero::zero(), Zero::zero());
- check(BigUint::new(~[1,2,3]),
- BigInt::from_biguint(Plus, BigUint::new(~[1,2,3])));
+ check(BigUint::new(vec!(1,2,3)),
+ BigInt::from_biguint(Plus, BigUint::new(vec!(1,2,3))));
}
static sum_triples: &'static [(&'static [BigDigit],
assert!(((one << 64) + one).is_odd());
}
- fn to_str_pairs() -> ~[ (BigUint, ~[(uint, ~str)]) ] {
+ fn to_str_pairs() -> Vec<(BigUint, Vec<(uint, ~str)>)> {
let bits = BigDigit::bits;
- ~[( Zero::zero(), ~[
+ vec!(( Zero::zero(), vec!(
(2, ~"0"), (3, ~"0")
- ]), ( BigUint::from_slice([ 0xff ]), ~[
+ )), ( BigUint::from_slice([ 0xff ]), vec!(
(2, ~"11111111"),
(3, ~"100110"),
(4, ~"3333"),
(14, ~"143"),
(15, ~"120"),
(16, ~"ff")
- ]), ( BigUint::from_slice([ 0xfff ]), ~[
+ )), ( BigUint::from_slice([ 0xfff ]), vec!(
(2, ~"111111111111"),
(4, ~"333333"),
(16, ~"fff")
- ]), ( BigUint::from_slice([ 1, 2 ]), ~[
+ )), ( BigUint::from_slice([ 1, 2 ]), vec!(
(2,
~"10" +
- str::from_chars(vec::from_elem(bits - 1, '0')) + "1"),
+ "0".repeat(bits - 1) + "1"),
(4,
~"2" +
- str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "1"),
+ "0".repeat(bits / 2 - 1) + "1"),
(10, match bits {
32 => ~"8589934593", 16 => ~"131073", _ => fail!()
}),
(16,
~"2" +
- str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "1")
- ]), ( BigUint::from_slice([ 1, 2, 3 ]), ~[
+ "0".repeat(bits / 4 - 1) + "1")
+ )), ( BigUint::from_slice([ 1, 2, 3 ]), vec!(
(2,
~"11" +
- str::from_chars(vec::from_elem(bits - 2, '0')) + "10" +
- str::from_chars(vec::from_elem(bits - 1, '0')) + "1"),
+ "0".repeat(bits - 2) + "10" +
+ "0".repeat(bits - 1) + "1"),
(4,
~"3" +
- str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "2" +
- str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "1"),
+ "0".repeat(bits / 2 - 1) + "2" +
+ "0".repeat(bits / 2 - 1) + "1"),
(10, match bits {
32 => ~"55340232229718589441",
16 => ~"12885032961",
_ => fail!()
}),
(16, ~"3" +
- str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "2" +
- str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "1")
- ]) ]
+ "0".repeat(bits / 4 - 1) + "2" +
+ "0".repeat(bits / 4 - 1) + "1")
+ )) )
}
#[test]
#[test]
fn test_bits() {
- assert_eq!(BigUint::new(~[0,0,0,0]).bits(), 0);
+ assert_eq!(BigUint::new(vec!(0,0,0,0)).bits(), 0);
let n: BigUint = FromPrimitive::from_uint(0).unwrap();
assert_eq!(n.bits(), 0);
let n: BigUint = FromPrimitive::from_uint(1).unwrap();
use std::num::{ToPrimitive, FromPrimitive};
use rand::{task_rng};
use std::u64;
+ use std::vec_ng::Vec;
#[test]
fn test_from_biguint() {
#[test]
fn test_cmp() {
let vs = [ &[2 as BigDigit], &[1, 1], &[2, 1], &[1, 1, 1] ];
- let mut nums = ~[];
+ let mut nums = Vec::new();
for s in vs.rev_iter() {
nums.push(BigInt::from_slice(Minus, *s));
}
nums.push(Zero::zero());
- nums.push_all_move(vs.map(|s| BigInt::from_slice(Plus, *s)));
+ nums.extend(&mut vs.iter().map(|s| BigInt::from_slice(Plus, *s)));
for (i, ni) in nums.iter().enumerate() {
for (j0, nj) in nums.slice(i, nums.len()).iter().enumerate() {
None);
assert_eq!(
- BigInt::from_biguint(Plus, BigUint::new(~[1, 2, 3, 4, 5])).to_i64(),
+ BigInt::from_biguint(Plus, BigUint::new(vec!(1, 2, 3, 4, 5))).to_i64(),
None);
assert_eq!(
- BigInt::from_biguint(Minus, BigUint::new(~[1, 0, 0, 1<<(BigDigit::bits-1)])).to_i64(),
+ BigInt::from_biguint(Minus, BigUint::new(vec!(1,0,0,1<<(BigDigit::bits-1)))).to_i64(),
None);
assert_eq!(
- BigInt::from_biguint(Minus, BigUint::new(~[1, 2, 3, 4, 5])).to_i64(),
+ BigInt::from_biguint(Minus, BigUint::new(vec!(1, 2, 3, 4, 5))).to_i64(),
None);
}
check(u64::MAX.to_bigint().unwrap(), u64::MAX);
assert_eq!(
- BigInt::from_biguint(Plus, BigUint::new(~[1, 2, 3, 4, 5])).to_u64(),
+ BigInt::from_biguint(Plus, BigUint::new(vec!(1, 2, 3, 4, 5))).to_u64(),
None);
let max_value: BigUint = FromPrimitive::from_u64(u64::MAX).unwrap();
assert_eq!(BigInt::from_biguint(Minus, max_value).to_u64(), None);
- assert_eq!(BigInt::from_biguint(Minus, BigUint::new(~[1, 2, 3, 4, 5])).to_u64(), None);
+ assert_eq!(BigInt::from_biguint(Minus, BigUint::new(vec!(1, 2, 3, 4, 5))).to_u64(), None);
}
#[test]
let zero: BigInt = Zero::zero();
let unsigned_zero: BigUint = Zero::zero();
let positive = BigInt::from_biguint(
- Plus, BigUint::new(~[1,2,3]));
+ Plus, BigUint::new(vec!(1,2,3)));
let negative = -positive;
check(zero, unsigned_zero);
- check(positive, BigUint::new(~[1,2,3]));
+ check(positive, BigUint::new(vec!(1,2,3)));
assert_eq!(negative.to_biguint(), None);
}
#[test]
fn test_neg() {
- assert!(-BigInt::new(Plus, ~[1, 1, 1]) ==
- BigInt::new(Minus, ~[1, 1, 1]));
- assert!(-BigInt::new(Minus, ~[1, 1, 1]) ==
- BigInt::new(Plus, ~[1, 1, 1]));
+ assert!(-BigInt::new(Plus, vec!(1, 1, 1)) ==
+ BigInt::new(Minus, vec!(1, 1, 1)));
+ assert!(-BigInt::new(Minus, vec!(1, 1, 1)) ==
+ BigInt::new(Plus, vec!(1, 1, 1)));
let zero: BigInt = Zero::zero();
assert_eq!(-zero, zero);
}
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
+#[allow(deprecated_owned_vector)];
extern crate rand;
use std::fmt;
use std::from_str::FromStr;
use std::num::{Zero,One,ToStrRadix,FromStrRadix,Round};
+use std::vec_ng::Vec;
use bigint::{BigInt, BigUint, Sign, Plus, Minus};
/// Represents the ratio between 2 numbers.
FromStr for Ratio<T> {
/// Parses `numer/denom`.
fn from_str(s: &str) -> Option<Ratio<T>> {
- let split: ~[&str] = s.splitn('/', 1).collect();
+ let split: Vec<&str> = s.splitn('/', 1).collect();
if split.len() < 2 {
return None
}
- let a_option: Option<T> = FromStr::from_str(split[0]);
+ let a_option: Option<T> = FromStr::from_str(split.as_slice()[0]);
a_option.and_then(|a| {
- let b_option: Option<T> = FromStr::from_str(split[1]);
+ let b_option: Option<T> = FromStr::from_str(split.as_slice()[1]);
b_option.and_then(|b| {
Some(Ratio::new(a.clone(), b.clone()))
})
FromStrRadix for Ratio<T> {
/// Parses `numer/denom` where the numbers are in base `radix`.
fn from_str_radix(s: &str, radix: uint) -> Option<Ratio<T>> {
- let split: ~[&str] = s.splitn('/', 1).collect();
+ let split: Vec<&str> = s.splitn('/', 1).collect();
if split.len() < 2 {
None
} else {
- let a_option: Option<T> = FromStrRadix::from_str_radix(split[0],
+ let a_option: Option<T> = FromStrRadix::from_str_radix(split.as_slice()[0],
radix);
a_option.and_then(|a| {
let b_option: Option<T> =
- FromStrRadix::from_str_radix(split[1], radix);
+ FromStrRadix::from_str_radix(split.as_slice()[1], radix);
b_option.and_then(|b| {
Some(Ratio::new(a.clone(), b.clone()))
})
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://static.rust-lang.org/doc/master")];
-#[feature(macro_rules, managed_boxes)];
+#[feature(macro_rules, managed_boxes, phase)];
+#[allow(deprecated_owned_vector)];
+
+#[cfg(test)]
+#[phase(syntax, link)] extern crate log;
use std::cast;
use std::kinds::marker;
use std::cast;
use std::vec_ng::Vec;
-use std::io::fs;
use std::io;
+use std::io::{fs, TempDir};
use std::libc;
use std::os;
use std::io::process::{ProcessConfig, Process, ProcessOutput};
use std::str;
use std::raw;
-use extra::tempfile::TempDir;
use syntax::abi;
pub static METADATA_FILENAME: &'static str = "rust.metadata.bin";
use std::ptr;
use std::str;
use std::io;
-use std::io::Process;
-use std::io::fs;
+use std::io::{fs, TempDir, Process};
use std::vec_ng::Vec;
use flate;
use serialize::hex::ToHex;
-use extra::tempfile::TempDir;
use syntax::abi;
use syntax::ast;
use syntax::ast_map::{PathElem, PathElems, PathName};
* system linkers understand.
*/
-pub fn find_crate_id(attrs: &[ast::Attribute],
- output: &OutputFilenames) -> CrateId {
+pub fn find_crate_id(attrs: &[ast::Attribute], out_filestem: &str) -> CrateId {
match attr::find_crateid(attrs) {
- None => from_str(output.out_filestem).unwrap(),
+ None => from_str(out_filestem).unwrap(),
Some(s) => s,
}
}
truncated_hash_result(&mut s).slice_to(8).to_owned()
}
-pub fn build_link_meta(krate: &ast::Crate,
- output: &OutputFilenames) -> LinkMeta {
+pub fn build_link_meta(krate: &ast::Crate, out_filestem: &str) -> LinkMeta {
let r = LinkMeta {
- crateid: find_crate_id(krate.attrs.as_slice(), output),
+ crateid: find_crate_id(krate.attrs.as_slice(), out_filestem),
crate_hash: Svh::calculate(krate),
};
info!("{}", r);
~"-o", out_filename.as_str().unwrap().to_owned(),
obj_filename.as_str().unwrap().to_owned()]);
+ // Stack growth requires statically linking a __morestack function. Note
+ // that this is listed *before* all other libraries, even though it may be
+ // used to resolve symbols in other libraries. The only case that this
+ // wouldn't be pulled in by the object file is if the object file had no
+ // functions.
+ //
+ // If we're building an executable, there must be at least one function (the
+ // main function), and if we're building a dylib then we don't need it for
+ // later libraries because they're all dylibs (not rlibs).
+ //
+ // I'm honestly not entirely sure why this needs to come first. Apparently
+ // the --as-needed flag above sometimes strips out libstd from the command
+ // line, but inserting this farther to the left makes the
+ // "rust_stack_exhausted" symbol an outstanding undefined symbol, which
+ // flags libstd as a required library (or whatever provides the symbol).
+ args.push(~"-lmorestack");
+
// When linking a dynamic library, we put the metadata into a section of the
// executable. This metadata is in a separate object file from the main
// object file, so we link that in here.
args.push_all(rpath::get_rpath_flags(sess, out_filename).as_slice());
}
- // Stack growth requires statically linking a __morestack function
- args.push(~"-lmorestack");
- // compiler-rt contains implementations of low-level LLVM helpers
- // It should go before platform and user libraries, so it has first dibs
- // at resolving symbols that also appear in libgcc.
+ // compiler-rt contains implementations of low-level LLVM helpers. This is
+ // used to resolve symbols from the object file we just created, as well as
+ // any system static libraries that may be expecting gcc instead. Most
+ // symbols in libgcc also appear in compiler-rt.
+ //
+ // This is the end of the command line, so this library is used to resolve
+ // *all* undefined symbols in all other libraries, and this is intentional.
args.push(~"-lcompiler-rt");
// Finally add all the linker arguments provided on the command line along
data_layout: match target_os {
abi::OsMacos => {
- ~"e-p:32:32:32" +
+ ~"E-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
"-v64:64:64-v128:64:128" +
}
abi::OsWin32 => {
- ~"e-p:32:32:32" +
+ ~"E-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
"-v64:64:64-v128:64:128" +
}
abi::OsLinux => {
- ~"e-p:32:32:32" +
+ ~"E-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
"-v64:64:64-v128:64:128" +
}
abi::OsAndroid => {
- ~"e-p:32:32:32" +
+ ~"E-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
"-v64:64:64-v128:64:128" +
}
abi::OsFreebsd => {
- ~"e-p:32:32:32" +
+ ~"E-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
"-v64:64:64-v128:64:128" +
use syntax::attr;
use syntax::attr::{AttrMetaMethods};
use syntax::codemap;
+use syntax::crateid::CrateId;
use syntax::diagnostic;
use syntax::diagnostic::Emitter;
use syntax::ext::base::CrateLoader;
StrInput(~str)
}
+impl Input {
+ fn filestem(&self) -> ~str {
+ match *self {
+ FileInput(ref ifile) => ifile.filestem_str().unwrap().to_str(),
+ StrInput(_) => ~"rust_out",
+ }
+ }
+}
+
pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, input: &Input)
-> ast::Crate {
let krate = time(sess.time_passes(), "parsing", (), |_| {
krate.encode(&mut json);
}
+ if sess.show_span() {
+ front::show_span::run(sess, &krate);
+ }
+
krate
}
/// standard library and prelude.
pub fn phase_2_configure_and_expand(sess: Session,
loader: &mut CrateLoader,
- mut krate: ast::Crate)
+ mut krate: ast::Crate,
+ crate_id: &CrateId)
-> (ast::Crate, syntax::ast_map::Map) {
let time_passes = sess.time_passes();
krate = time(time_passes, "expansion", krate, |krate| {
let cfg = syntax::ext::expand::ExpansionConfig {
loader: loader,
- deriving_hash_type_parameter: sess.features.default_type_params.get()
+ deriving_hash_type_parameter: sess.features.default_type_params.get(),
+ crate_id: crate_id.clone(),
};
syntax::ext::expand::expand_crate(sess.parse_sess,
cfg,
debug!("invoked with --parse-only, returning early from compile_input");
return true;
}
+ if sess.show_span() {
+ return true;
+ }
return sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0;
}
input: &Input,
outputs: &OutputFilenames,
krate: &ast::Crate) -> io::IoResult<()> {
- let id = link::find_crate_id(krate.attrs.as_slice(), outputs);
+ let id = link::find_crate_id(krate.attrs.as_slice(), outputs.out_filestem);
let mut out_filenames = Vec::new();
for output_type in sess.opts.output_types.iter() {
// We need nested scopes here, because the intermediate results can keep
// large chunks of memory alive and we want to free them as soon as
// possible to keep the peak memory usage low
- let (outputs, trans) = {
+ let outputs;
+ let trans = {
let (expanded_crate, ast_map) = {
let krate = phase_1_parse_input(sess, cfg, input);
- if sess.show_span() {
- front::show_span::run(sess, &krate);
- return;
- }
if stop_after_phase_1(sess) { return; }
- let loader = &mut Loader::new(sess);
- phase_2_configure_and_expand(sess, loader, krate)
- };
- let outputs = build_output_filenames(input,
+ outputs = build_output_filenames(input,
outdir,
output,
- expanded_crate.attrs.as_slice(),
+ krate.attrs.as_slice(),
sess);
+ let loader = &mut Loader::new(sess);
+ let id = link::find_crate_id(krate.attrs.as_slice(),
+ outputs.out_filestem);
+ phase_2_configure_and_expand(sess, loader, krate, &id)
+ };
write_out_deps(sess, input, &outputs, &expanded_crate).unwrap();
let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
if stop_after_phase_3(sess) { return; }
- let trans = phase_4_translate_to_llvm(sess, expanded_crate,
- &analysis, &outputs);
- (outputs, trans)
+ phase_4_translate_to_llvm(sess, expanded_crate, &analysis, &outputs)
};
phase_5_run_llvm_passes(sess, &trans, &outputs);
if stop_after_phase_5(sess) { return; }
input: &Input,
ppm: PpMode) {
let krate = phase_1_parse_input(sess, cfg, input);
+ let id = link::find_crate_id(krate.attrs.as_slice(), input.filestem());
let (krate, ast_map, is_expanded) = match ppm {
PpmExpanded | PpmExpandedIdentified | PpmTyped => {
let loader = &mut Loader::new(sess);
- let (krate, ast_map) = phase_2_configure_and_expand(sess, loader, krate);
+ let (krate, ast_map) = phase_2_configure_and_expand(sess, loader,
+ krate, &id);
(krate, Some(ast_map), true)
}
_ => (krate, None, false)
None => Path::new(".")
};
- let mut stem = match *input {
- // FIXME (#9639): This needs to handle non-utf8 paths
- FileInput(ref ifile) => ifile.filestem_str().unwrap().to_str(),
- StrInput(_) => ~"rust_out"
- };
+ let mut stem = input.filestem();
// If a crateid is present, we use it as the link name
let crateid = attr::find_crateid(attrs);
ExpansionConfig {
loader: loader,
deriving_hash_type_parameter: false,
+ crate_id: from_str("test").unwrap(),
}),
path: RefCell::new(Vec::new()),
testfns: RefCell::new(Vec::new()),
// with our list of tests
let mainfn = (quote_item!(&cx.ext_cx,
pub fn main() {
+ #[allow(deprecated_owned_vector)];
#[main];
test::test_main_static(::std::os::args(), TESTS);
}
html_root_url = "http://static.rust-lang.org/doc/master")];
#[allow(deprecated)];
+#[allow(deprecated_owned_vector)];
#[feature(macro_rules, globs, struct_variant, managed_boxes)];
-#[feature(quote, default_type_params)];
+#[feature(quote, default_type_params, phase)];
-extern crate extra;
extern crate flate;
extern crate arena;
extern crate syntax;
extern crate getopts;
extern crate collections;
extern crate time;
+#[phase(syntax, link)]
+extern crate log;
use back::link;
use driver::session;
pub mod llvmdeps;
}
+static BUG_REPORT_URL: &'static str =
+ "http://static.rust-lang.org/doc/master/complement-bugreport.html";
+
pub fn version(argv0: &str) {
let vers = match option_env!("CFG_VERSION") {
Some(vers) => vers,
let attrs = parse_crate_attrs(sess, &input);
let t_outputs = d::build_output_filenames(&input, &odir, &ofile,
attrs.as_slice(), sess);
- let id = link::find_crate_id(attrs.as_slice(), &t_outputs);
+ let id = link::find_crate_id(attrs.as_slice(), t_outputs.out_filestem);
if crate_id {
println!("{}", id.to_str());
// Task failed without emitting a fatal diagnostic
if !value.is::<diagnostic::FatalError>() {
let mut emitter = diagnostic::EmitterWriter::stderr();
- emitter.emit(
- None,
- diagnostic::ice_msg("unexpected failure"),
- diagnostic::Error);
+
+ // a .span_bug or .bug call has already printed what
+ // it wants to print.
+ if !value.is::<diagnostic::ExplicitBug>() {
+ emitter.emit(
+ None,
+ "unexpected failure",
+ diagnostic::Bug);
+ }
let xs = [
- ~"the compiler hit an unexpected failure path. \
- this is a bug",
+ ~"the compiler hit an unexpected failure path. this is a bug.",
+ "we would appreciate a bug report: " + BUG_REPORT_URL,
+ ~"run with `RUST_BACKTRACE=1` for a backtrace",
];
for note in xs.iter() {
emitter.emit(None, *note, diagnostic::Note)
}
- println!("{}", r.read_to_str());
+ match r.read_to_str() {
+ Ok(s) => println!("{}", s),
+ Err(e) => emitter.emit(None,
+ format!("failed to read internal stderr: {}", e),
+ diagnostic::Error),
+ }
}
// Fail so the process returns a failure code, but don't pollute the
use std::cell::RefCell;
use std::vec_ng::Vec;
+use std::c_vec::CVec;
use collections::HashMap;
-use extra::c_vec::CVec;
use syntax::ast;
use syntax::parse::token::IdentInterner;
use syntax::crateid::CrateId;
self.used_link_args.with_mut(|s| s.clear());
}
+ // This method is used when generating the command line to pass through to
+ // system linker. The linker expects undefined symbols on the left of the
+ // command line to be defined in libraries on the right, not the other way
+ // around. For more info, see some comments in the add_used_library function
+ // below.
+ //
+ // In order to get this left-to-right dependency ordering, we perform a
+ // topological sort of all crates putting the leaves at the right-most
+ // positions.
pub fn get_used_crates(&self, prefer: LinkagePreference)
-> Vec<(ast::CrateNum, Option<Path>)> {
+ let mut ordering = Vec::new();
+ fn visit(cstore: &CStore, cnum: ast::CrateNum,
+ ordering: &mut Vec<ast::CrateNum>) {
+ if ordering.as_slice().contains(&cnum) { return }
+ let meta = cstore.get_crate_data(cnum);
+ for (_, &dep) in meta.cnum_map.borrow().get().iter() {
+ visit(cstore, dep, ordering);
+ }
+ ordering.push(cnum);
+ };
+ for (&num, _) in self.metas.borrow().get().iter() {
+ visit(self, num, &mut ordering);
+ }
+ ordering.as_mut_slice().reverse();
+ let ordering = ordering.as_slice();
let used_crate_sources = self.used_crate_sources.borrow();
- used_crate_sources.get()
+ let mut libs = used_crate_sources.get()
.iter()
.map(|src| (src.cnum, match prefer {
RequireDynamic => src.dylib.clone(),
RequireStatic => src.rlib.clone(),
}))
- .collect()
+ .collect::<Vec<(ast::CrateNum, Option<Path>)>>();
+ libs.sort_by(|&(a, _), &(b, _)| {
+ ordering.position_elem(&a).cmp(&ordering.position_elem(&b))
+ });
+ libs
}
pub fn add_used_library(&self, lib: ~str, kind: NativeLibaryKind) {
self.straightline(expr, pred, [e])
}
- ast::ExprLogLevel |
ast::ExprMac(..) |
ast::ExprInlineAsm(..) |
ast::ExprFnBlock(..) |
self.walk_exprs([l, r], in_out, loop_scopes);
}
- ast::ExprLogLevel |
ast::ExprLit(..) |
ast::ExprPath(..) => {}
UnusedMustUse,
UnusedResult,
+ DeprecatedOwnedVector,
+
Warnings,
}
lint: UnusedResult,
desc: "unused result of an expression in a statement",
default: allow,
- })
+ }),
+
+ ("deprecated_owned_vector",
+ LintSpec {
+ lint: DeprecatedOwnedVector,
+ desc: "use of a `~[T]` vector",
+ default: warn
+ }),
];
/*
"crate_map", "cfg", "doc", "export_name", "link_section",
"no_mangle", "static_assert", "unsafe_no_drop_flag", "packed",
"simd", "repr", "deriving", "unsafe_destructor", "link", "phase",
- "macro_export", "must_use",
+ "macro_export", "must_use", "automatically_derived",
//mod-level
"path", "link_name", "link_args", "macro_escape", "no_implicit_prelude",
}
}
+fn check_deprecated_owned_vector(cx: &Context, e: &ast::Expr) {
+ let t = ty::expr_ty(cx.tcx, e);
+ match ty::get(t).sty {
+ ty::ty_vec(_, ty::vstore_uniq) => {
+ cx.span_lint(DeprecatedOwnedVector, e.span,
+ "use of deprecated `~[]` vector; replaced by `std::vec_ng::Vec`")
+ }
+ _ => {}
+ }
+}
+
fn check_item_non_camel_case_types(cx: &Context, it: &ast::Item) {
fn is_camel_case(ident: ast::Ident) -> bool {
let ident = token::get_ident(ident);
check_type_limits(self, e);
check_unused_casts(self, e);
+ check_deprecated_owned_vector(self, e);
visit::walk_expr(self, e, ());
}
// otherwise, live nodes are not required:
ExprIndex(..) | ExprField(..) | ExprVstore(..) | ExprVec(..) |
- ExprCall(..) | ExprMethodCall(..) | ExprTup(..) | ExprLogLevel |
+ ExprCall(..) | ExprMethodCall(..) | ExprTup(..) |
ExprBinary(..) | ExprAddrOf(..) |
ExprCast(..) | ExprUnary(..) | ExprBreak(_) |
ExprAgain(_) | ExprLit(_) | ExprRet(..) | ExprBlock(..) |
}
ExprInlineAsm(ref ia) => {
- let succ = ia.inputs.rev_iter().fold(succ, |succ, &(_, expr)| {
- self.propagate_through_expr(expr, succ)
- });
- ia.outputs.rev_iter().fold(succ, |succ, &(_, expr)| {
+ let succ = ia.outputs.rev_iter().fold(succ, |succ, &(_, expr)| {
// see comment on lvalues in
// propagate_through_lvalue_components()
let succ = self.write_lvalue(expr, succ, ACC_WRITE);
self.propagate_through_lvalue_components(expr, succ)
+ });
+ // Inputs are executed first. Propagate last because of rev order
+ ia.inputs.rev_iter().fold(succ, |succ, &(_, expr)| {
+ self.propagate_through_expr(expr, succ)
})
}
- ExprLogLevel |
ExprLit(..) => {
succ
}
// no correctness conditions related to liveness
ExprCall(..) | ExprMethodCall(..) | ExprIf(..) | ExprMatch(..) |
ExprWhile(..) | ExprLoop(..) | ExprIndex(..) | ExprField(..) |
- ExprVstore(..) | ExprVec(..) | ExprTup(..) | ExprLogLevel |
+ ExprVstore(..) | ExprVec(..) | ExprTup(..) |
ExprBinary(..) |
ExprCast(..) | ExprUnary(..) | ExprRet(..) | ExprBreak(..) |
ExprAgain(..) | ExprLit(_) | ExprBlock(..) |
ast::ExprUnary(..) |
ast::ExprMethodCall(..) | ast::ExprCast(..) | ast::ExprVstore(..) |
ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) |
- ast::ExprLogLevel | ast::ExprBinary(..) | ast::ExprWhile(..) |
+ ast::ExprBinary(..) | ast::ExprWhile(..) |
ast::ExprBlock(..) | ast::ExprLoop(..) | ast::ExprMatch(..) |
ast::ExprLit(..) | ast::ExprBreak(..) | ast::ExprMac(..) |
ast::ExprAgain(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
self.use_expr(base, Read);
}
- ExprLogLevel |
ExprInlineAsm(..) |
ExprBreak(..) |
ExprAgain(..) |
use driver::driver::OutputFilenames;
use driver::driver::{CrateAnalysis, CrateTranslation};
use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
-use lib::llvm::{llvm, True, Vector};
+use lib::llvm::{llvm, Vector};
use lib;
use metadata::common::LinkMeta;
use metadata::{csearch, encoder};
}
}
-pub fn decl_gc_metadata(ccx: &CrateContext, llmod_id: &str) {
- if !ccx.sess.opts.gc || !ccx.uses_gc {
- return;
- }
-
- let gc_metadata_name = ~"_gc_module_metadata_" + llmod_id;
- let gc_metadata = gc_metadata_name.with_c_str(|buf| {
- unsafe {
- llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
- }
- });
- unsafe {
- llvm::LLVMSetGlobalConstant(gc_metadata, True);
- lib::llvm::SetLinkage(gc_metadata, lib::llvm::ExternalLinkage);
-
- let mut module_data = ccx.module_data.borrow_mut();
- module_data.get().insert(~"_gc_module_metadata", gc_metadata);
- }
-}
-
-pub fn create_module_map(ccx: &CrateContext) -> (ValueRef, uint) {
- let str_slice_type = Type::struct_([Type::i8p(), ccx.int_type], false);
- let elttype = Type::struct_([str_slice_type, ccx.int_type], false);
- let maptype = {
- let module_data = ccx.module_data.borrow();
- Type::array(&elttype, module_data.get().len() as u64)
- };
- let map = "_rust_mod_map".with_c_str(|buf| {
- unsafe {
- llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf)
- }
- });
- lib::llvm::SetLinkage(map, lib::llvm::InternalLinkage);
- let mut elts: Vec<ValueRef> = Vec::new();
-
- // This is not ideal, but the borrow checker doesn't
- // like the multiple borrows. At least, it doesn't
- // like them on the current snapshot. (2013-06-14)
- let keys = {
- let mut keys = Vec::new();
- let module_data = ccx.module_data.borrow();
- for (k, _) in module_data.get().iter() {
- keys.push(k.clone());
- }
- keys
- };
-
- for key in keys.iter() {
- let llstrval = C_str_slice(ccx, token::intern_and_get_ident(*key));
- let module_data = ccx.module_data.borrow();
- let val = *module_data.get().find_equiv(key).unwrap();
- let v_ptr = p2i(ccx, val);
- let elt = C_struct([
- llstrval,
- v_ptr
- ], false);
- elts.push(elt);
- }
- unsafe {
- llvm::LLVMSetInitializer(map, C_array(elttype, elts.as_slice()));
- }
- return (map, keys.len())
-}
-
pub fn symname(name: &str, hash: &str, vers: &str) -> ~str {
let path = [PathName(token::intern(name))];
link::exported_name(ast_map::Values(path.iter()).chain(None), hash, vers)
mapmeta.crateid.version_or_default())
};
- let slicetype = Type::struct_([int_type, int_type], false);
let maptype = Type::struct_([
Type::i32(), // version
- slicetype, // child modules
- slicetype, // sub crate-maps
int_type.ptr_to(), // event loop factory
], false);
let map = sym_name.with_c_str(|buf| {
}
pub fn fill_crate_map(ccx: @CrateContext, map: ValueRef) {
- let mut subcrates: Vec<ValueRef> = Vec::new();
- let mut i = 1;
- let cstore = ccx.sess.cstore;
- while cstore.have_crate_data(i) {
- let cdata = cstore.get_crate_data(i);
- let nm = symname(format!("_rust_crate_map_{}", cdata.name),
- cstore.get_crate_hash(i).as_str(),
- cstore.get_crate_id(i).version_or_default());
- let cr = nm.with_c_str(|buf| {
- unsafe {
- llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
- }
- });
- subcrates.push(p2i(ccx, cr));
- i += 1;
- }
let event_loop_factory = match ccx.tcx.lang_items.event_loop_factory() {
Some(did) => unsafe {
if is_local(did) {
None => C_null(ccx.int_type.ptr_to())
};
unsafe {
- let maptype = Type::array(&ccx.int_type, subcrates.len() as u64);
- let vec_elements = "_crate_map_child_vectors".with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf)
- });
- lib::llvm::SetLinkage(vec_elements, lib::llvm::InternalLinkage);
-
- llvm::LLVMSetInitializer(vec_elements,
- C_array(ccx.int_type, subcrates.as_slice()));
- let (mod_map, mod_count) = create_module_map(ccx);
-
llvm::LLVMSetInitializer(map, C_struct(
[C_i32(2),
- C_struct([
- p2i(ccx, mod_map),
- C_uint(ccx, mod_count)
- ], false),
- C_struct([
- p2i(ccx, vec_elements),
- C_uint(ccx, subcrates.len())
- ], false),
event_loop_factory,
], false));
}
}
}
- let link_meta = link::build_link_meta(&krate, output);
+ let link_meta = link::build_link_meta(&krate, output.out_filestem);
// Append ".rs" to crate name as LLVM module identifier.
//
trans_mod(ccx, &krate.module);
}
- decl_gc_metadata(ccx, llmod_id);
fill_crate_map(ccx, ccx.crate_map);
// win32: wart with exporting crate_map symbol
ty::type_is_nil(ty) || ty::type_is_bot(ty) || ty::type_is_empty(ccx.tcx, ty)
}
+/// Generates a unique symbol based off the name given. This is used to create
+/// unique symbols for things like closures.
pub fn gensym_name(name: &str) -> PathElem {
- PathName(token::gensym(name))
+ let num = token::gensym(name);
+ // use one colon which will get translated to a period by the mangler, and
+ // we're guaranteed that `num` is globally unique for this crate.
+ PathName(token::gensym(format!("{}:{}", name, num)))
}
pub struct tydesc_info {
// Cache of closure wrappers for bare fn's.
closure_bare_wrapper_cache: RefCell<HashMap<ValueRef, ValueRef>>,
- module_data: RefCell<HashMap<~str, ValueRef>>,
lltypes: RefCell<HashMap<ty::t, Type>>,
llsizingtypes: RefCell<HashMap<ty::t, Type>>,
adt_reprs: RefCell<HashMap<ty::t, @adt::Repr>>,
extern_const_values: RefCell::new(DefIdMap::new()),
impl_method_cache: RefCell::new(HashMap::new()),
closure_bare_wrapper_cache: RefCell::new(HashMap::new()),
- module_data: RefCell::new(HashMap::new()),
lltypes: RefCell::new(HashMap::new()),
llsizingtypes: RefCell::new(HashMap::new()),
adt_reprs: RefCell::new(HashMap::new()),
scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
match exp.node {
- ast::ExprLogLevel |
ast::ExprLit(_) |
ast::ExprBreak(_) |
ast::ExprAgain(_) |
#[allow(non_camel_case_types)];
use back::abi;
-use back::link;
-use lib::llvm::{ValueRef, llvm, SetLinkage, False};
+use lib::llvm::{ValueRef, llvm};
use lib;
use metadata::csearch;
use middle::trans::_match;
use std::vec;
use std::vec_ng::Vec;
use syntax::ast;
-use syntax::ast_map;
use syntax::codemap;
-use syntax::parse::token;
use syntax::print::pprust::{expr_to_str};
// Destinations
// Datum output mode means this is a scalar cast:
trans_imm_cast(bcx, val, expr.id)
}
- ast::ExprLogLevel => {
- trans_log_level(bcx)
- }
_ => {
bcx.tcx().sess.span_bug(
expr.span,
return result_datum.store_to(bcx, dst_datum.val);
}
-fn trans_log_level<'a>(bcx: &'a Block<'a>) -> DatumBlock<'a, Expr> {
- let _icx = push_ctxt("trans_log_level");
- let ccx = bcx.ccx();
-
- let (modpath, modname) = {
- let srccrate = {
- let external_srcs = ccx.external_srcs.borrow();
- match external_srcs.get().find(&bcx.fcx.id) {
- Some(&src) => {
- ccx.sess.cstore.get_crate_data(src.krate).name.clone()
- }
- None => ccx.link_meta.crateid.name.to_str(),
- }
- };
- bcx.tcx().map.with_path(bcx.fcx.id, |path| {
- let first = ast_map::PathMod(token::intern(srccrate));
- let mut path = Some(first).move_iter().chain(path).filter(|e| {
- match *e {
- ast_map::PathMod(_) => true,
- _ => false
- }
- });
- let modpath: Vec<ast_map::PathElem> = path.collect();
- let modname = ast_map::path_to_str(ast_map::Values(modpath.iter()));
- (modpath, modname)
- })
- };
-
- let module_data_exists;
- {
- let module_data = ccx.module_data.borrow();
- module_data_exists = module_data.get().contains_key(&modname);
- }
-
- let global = if module_data_exists {
- let mut module_data = ccx.module_data.borrow_mut();
- module_data.get().get_copy(&modname)
- } else {
- let s = link::mangle_internal_name_by_path_and_seq(
- ast_map::Values(modpath.iter()).chain(None), "loglevel");
- let global;
- unsafe {
- global = s.with_c_str(|buf| {
- llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
- });
- llvm::LLVMSetGlobalConstant(global, False);
- llvm::LLVMSetInitializer(global, C_null(Type::i32()));
- lib::llvm::SetLinkage(global, lib::llvm::InternalLinkage);
- }
- {
- let mut module_data = ccx.module_data.borrow_mut();
- module_data.get().insert(modname, global);
- global
- }
- };
-
- immediate_rvalue_bcx(bcx, Load(bcx, global), ty::mk_u32()).to_expr_datumblock()
-}
fn auto_ref<'a>(bcx: &'a Block<'a>,
datum: Datum<Expr>,
ast::ExprForLoop(..) => fail!("non-desugared expr_for_loop"),
- ast::ExprLogLevel |
ast::ExprLit(_) | // Note: LitStr is carved out above
ast::ExprUnary(..) |
ast::ExprAddrOf(..) |
tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
}
ast::TyInfer => {
- // ty_infer should only appear as the type of arguments or return
- // values in a fn_expr, or as the type of local variables. Both of
- // these cases are handled specially and should not descend into this
- // routine.
- this.tcx().sess.span_bug(
- ast_ty.span,
- "found `ty_infer` in unexpected place");
+ // TyInfer also appears as the type of arguments or return
+ // values in a ExprFnBlock or ExprProc, or as the type of
+ // local variables. Both of these cases are handled specially
+ // and will not descend into this routine.
+ this.ty_infer(ast_ty.span)
}
});
}
fcx.write_bot(id);
}
- ast::ExprLogLevel => {
- fcx.write_ty(id, ty::mk_u32())
- }
ast::ExprParen(a) => {
check_expr_with_opt_hint_and_lvalue_pref(fcx, a, expected, lvalue_pref);
fcx.write_ty(id, fcx.expr_ty(a));
}
fn ty_infer(&self, span: Span) -> ty::t {
- self.tcx.sess.span_bug(span, "found `ty_infer` in unexpected place");
+ self.tcx.sess.span_err(span, "the type placeholder `_` is not \
+ allowed within types on item signatures.");
+ ty::mk_err()
}
}
let krate = phase_1_parse_input(sess, cfg, &input);
let loader = &mut Loader::new(sess);
- let (krate, ast_map) = phase_2_configure_and_expand(sess, loader, krate);
+ let id = from_str("rustdoc").unwrap();
+ let (krate, ast_map) = phase_2_configure_and_expand(sess, loader,
+ krate, &id);
let driver::driver::CrateAnalysis {
exported_items, public_items, ty_cx, ..
} = phase_3_run_analysis_passes(sess, &krate, ast_map);
#[crate_type = "dylib"];
#[crate_type = "rlib"];
-#[feature(globs, struct_variant, managed_boxes, macro_rules)];
+#[allow(deprecated_owned_vector)];
+#[feature(globs, struct_variant, managed_boxes, macro_rules, phase)];
extern crate syntax;
extern crate rustc;
-extern crate extra;
extern crate serialize;
extern crate sync;
extern crate getopts;
extern crate collections;
extern crate testing = "test";
extern crate time;
+#[phase(syntax, link)]
+extern crate log;
use std::cell::RefCell;
use std::local_data;
use std::cell::RefCell;
use std::char;
use std::io;
-use std::io::Process;
+use std::io::{Process, TempDir};
use std::local_data;
use std::os;
use std::str;
use collections::HashSet;
use testing;
-use extra::tempfile::TempDir;
use rustc::back::link;
use rustc::driver::driver;
use rustc::driver::session;
let cfg = driver::build_configuration(sess);
let krate = driver::phase_1_parse_input(sess, cfg, &input);
let loader = &mut Loader::new(sess);
- let (krate, _) = driver::phase_2_configure_and_expand(sess, loader, krate);
+ let id = from_str("rustdoc-test").unwrap();
+ let (krate, _) = driver::phase_2_configure_and_expand(sess, loader, krate,
+ &id);
let ctx = @core::DocContext {
krate: krate,
let mut prog = ~r"
#[deny(warnings)];
#[allow(unused_variable, dead_assignment, unused_mut, attribute_usage, dead_code)];
+
+// FIXME: remove when ~[] disappears from tests.
+#[allow(deprecated_owned_vector)];
";
if loose_feature_gating {
}
if !s.contains("extern crate") {
- if s.contains("extra") {
- prog.push_str("extern crate extra;\n");
- }
if s.contains(cratename) {
prog.push_str(format!("extern crate {};\n", cratename));
}
#[feature(macro_rules)];
#[deny(unused_result, unused_must_use)];
#[allow(visible_private_types)];
+#[allow(deprecated_owned_vector)];
#[cfg(test)] extern crate green;
read_access: self.read_access.clone(),
} as ~rtio::RtioTcpStream
}
+
+ fn close_write(&mut self) -> Result<(), IoError> {
+ struct Ctx {
+ slot: Option<BlockedTask>,
+ status: c_int,
+ }
+ let mut req = Request::new(uvll::UV_SHUTDOWN);
+
+ return match unsafe {
+ uvll::uv_shutdown(req.handle, self.handle, shutdown_cb)
+ } {
+ 0 => {
+ req.defuse(); // uv callback now owns this request
+ let mut cx = Ctx { slot: None, status: 0 };
+
+ wait_until_woken_after(&mut cx.slot, &self.uv_loop(), || {
+ req.set_data(&cx);
+ });
+
+ status_to_io_result(cx.status)
+ }
+ n => Err(uv_error_to_io_error(UvError(n)))
+ };
+
+ extern fn shutdown_cb(req: *uvll::uv_shutdown_t, status: libc::c_int) {
+ let req = Request::wrap(req);
+ assert!(status != uvll::ECANCELED);
+ let cx: &mut Ctx = unsafe { req.get_data() };
+ cx.status = status;
+ wakeup(&mut cx.slot);
+ }
+ }
}
impl UvHandle<uvll::uv_tcp_t> for TcpWatcher {
pub type uv_pipe_t = c_void;
pub type uv_tty_t = c_void;
pub type uv_signal_t = c_void;
+pub type uv_shutdown_t = c_void;
pub struct uv_timespec_t {
tv_sec: libc::c_long,
pub type uv_signal_cb = extern "C" fn(handle: *uv_signal_t,
signum: c_int);
pub type uv_fs_cb = extern "C" fn(req: *uv_fs_t);
+pub type uv_shutdown_cb = extern "C" fn(req: *uv_shutdown_t, status: c_int);
#[cfg(unix)] pub type uv_uid_t = libc::types::os::arch::posix88::uid_t;
#[cfg(unix)] pub type uv_gid_t = libc::types::os::arch::posix88::gid_t;
on_alloc: uv_alloc_cb,
on_read: uv_read_cb) -> c_int;
pub fn uv_read_stop(stream: *uv_stream_t) -> c_int;
+ pub fn uv_shutdown(req: *uv_shutdown_t, handle: *uv_stream_t,
+ cb: uv_shutdown_cb) -> c_int;
// idle bindings
pub fn uv_idle_init(l: *uv_loop_t, i: *uv_idle_t) -> c_int;
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
use std::char;
use std::cmp;
use std::fmt;
use std::fmt::Show;
use std::option::{Option, Some, None};
+use std::vec_ng::Vec;
/// An identifier in the pre-release or build metadata. If the identifier can
/// be parsed as a decimal value, it will be represented with `Numeric`.
/// fixes are made.
patch: uint,
/// The pre-release version identifier, if one exists.
- pre: ~[Identifier],
+ pre: Vec<Identifier>,
/// The build metadata, ignored when determining version precedence.
- build: ~[Identifier],
+ build: Vec<Identifier>,
}
impl fmt::Show for Version {
}
}
}
- debug!("extracted nonempty prefix: {}", buf);
(buf, ch)
}
None => return None
};
- let mut pre = ~[];
- let mut build = ~[];
+ let mut pre = vec!();
+ let mut build = vec!();
let mut ch = ch;
if ch == Some('-') {
major: 1u,
minor: 2u,
patch: 3u,
- pre: ~[],
- build: ~[],
+ pre: vec!(),
+ build: vec!(),
}));
assert!(parse(" 1.2.3 ") == Some(Version {
major: 1u,
minor: 2u,
patch: 3u,
- pre: ~[],
- build: ~[],
+ pre: vec!(),
+ build: vec!(),
}));
assert!(parse("1.2.3-alpha1") == Some(Version {
major: 1u,
minor: 2u,
patch: 3u,
- pre: ~[AlphaNumeric(~"alpha1")],
- build: ~[]
+ pre: vec!(AlphaNumeric(~"alpha1")),
+ build: vec!(),
}));
assert!(parse(" 1.2.3-alpha1 ") == Some(Version {
major: 1u,
minor: 2u,
patch: 3u,
- pre: ~[AlphaNumeric(~"alpha1")],
- build: ~[]
+ pre: vec!(AlphaNumeric(~"alpha1")),
+ build: vec!()
}));
assert!(parse("1.2.3+build5") == Some(Version {
major: 1u,
minor: 2u,
patch: 3u,
- pre: ~[],
- build: ~[AlphaNumeric(~"build5")]
+ pre: vec!(),
+ build: vec!(AlphaNumeric(~"build5"))
}));
assert!(parse(" 1.2.3+build5 ") == Some(Version {
major: 1u,
minor: 2u,
patch: 3u,
- pre: ~[],
- build: ~[AlphaNumeric(~"build5")]
+ pre: vec!(),
+ build: vec!(AlphaNumeric(~"build5"))
}));
assert!(parse("1.2.3-alpha1+build5") == Some(Version {
major: 1u,
minor: 2u,
patch: 3u,
- pre: ~[AlphaNumeric(~"alpha1")],
- build: ~[AlphaNumeric(~"build5")]
+ pre: vec!(AlphaNumeric(~"alpha1")),
+ build: vec!(AlphaNumeric(~"build5"))
}));
assert!(parse(" 1.2.3-alpha1+build5 ") == Some(Version {
major: 1u,
minor: 2u,
patch: 3u,
- pre: ~[AlphaNumeric(~"alpha1")],
- build: ~[AlphaNumeric(~"build5")]
+ pre: vec!(AlphaNumeric(~"alpha1")),
+ build: vec!(AlphaNumeric(~"build5"))
}));
assert!(parse("1.2.3-1.alpha1.9+build5.7.3aedf ") == Some(Version {
major: 1u,
minor: 2u,
patch: 3u,
- pre: ~[Numeric(1),AlphaNumeric(~"alpha1"),Numeric(9)],
- build: ~[AlphaNumeric(~"build5"),
+ pre: vec!(Numeric(1),AlphaNumeric(~"alpha1"),Numeric(9)),
+ build: vec!(AlphaNumeric(~"build5"),
Numeric(7),
- AlphaNumeric(~"3aedf")]
+ AlphaNumeric(~"3aedf"))
}));
}
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
#[allow(missing_doc)];
#[forbid(non_camel_case_types)];
-#[feature(macro_rules, managed_boxes, default_type_params)];
+#[feature(macro_rules, managed_boxes, default_type_params, phase)];
// NOTE remove the following two attributes after the next snapshot.
#[allow(unrecognized_lint)];
#[allow(default_type_param_usage)];
+#[allow(deprecated_owned_vector)];
// test harness access
#[cfg(test)]
extern crate test;
+#[phase(syntax, link)]
+extern crate log;
extern crate collections;
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Library to interface with chunks of memory allocated in C.
+//!
+//! It is often desirable to safely interface with memory allocated from C,
+//! encapsulating the unsafety into allocation and destruction time. Indeed,
+//! allocating memory externally is currently the only way to give Rust shared
+//! mut state with C programs that keep their own references; vectors are
+//! unsuitable because they could be reallocated or moved at any time, and
+//! importing C memory into a vector takes a one-time snapshot of the memory.
+//!
+//! This module simplifies the usage of such external blocks of memory. Memory
+//! is encapsulated into an opaque object after creation; the lifecycle of the
+//! memory can be optionally managed by Rust, if an appropriate destructor
+//! closure is provided. Safety is ensured by bounds-checking accesses, which
+//! are marshalled through get and set functions.
+//!
+//! There are three unsafe functions: the two constructors, and the
+//! unwrap method. The constructors are unsafe for the
+//! obvious reason (they act on a pointer that cannot be checked inside the
+//! method), but `unwrap()` is somewhat more subtle in its unsafety.
+//! It returns the contained pointer, but at the same time destroys the CVec
+//! without running its destructor. This can be used to pass memory back to
+//! C, but care must be taken that the ownership of underlying resources are
+//! handled correctly, i.e. that allocated memory is eventually freed
+//! if necessary.
+
+use cast;
+use container::Container;
+use ptr;
+use ptr::RawPtr;
+use raw;
+use option::{Option, Some, None};
+use ops::Drop;
+
+/// The type representing a foreign chunk of memory
+pub struct CVec<T> {
+ priv base: *mut T,
+ priv len: uint,
+ priv dtor: Option<proc()>,
+}
+
+#[unsafe_destructor]
+impl<T> Drop for CVec<T> {
+ fn drop(&mut self) {
+ match self.dtor.take() {
+ None => (),
+ Some(f) => f()
+ }
+ }
+}
+
+impl<T> CVec<T> {
+ /// Create a `CVec` from a raw pointer to a buffer with a given length.
+ ///
+ /// Fails if the given pointer is null. The returned vector will not attempt
+ /// to deallocate the vector when dropped.
+ ///
+ /// # Arguments
+ ///
+ /// * base - A raw pointer to a buffer
+ /// * len - The number of elements in the buffer
+ pub unsafe fn new(base: *mut T, len: uint) -> CVec<T> {
+ assert!(base != ptr::mut_null());
+ CVec {
+ base: base,
+ len: len,
+ dtor: None,
+ }
+ }
+
+ /// Create a `CVec` from a foreign buffer, with a given length,
+ /// and a function to run upon destruction.
+ ///
+ /// Fails if the given pointer is null.
+ ///
+ /// # Arguments
+ ///
+ /// * base - A foreign pointer to a buffer
+ /// * len - The number of elements in the buffer
+ /// * dtor - A proc to run when the value is destructed, useful
+ /// for freeing the buffer, etc.
+ pub unsafe fn new_with_dtor(base: *mut T, len: uint,
+ dtor: proc()) -> CVec<T> {
+ assert!(base != ptr::mut_null());
+ CVec {
+ base: base,
+ len: len,
+ dtor: Some(dtor),
+ }
+ }
+
+ /// View the stored data as a slice.
+ pub fn as_slice<'a>(&'a self) -> &'a [T] {
+ unsafe {
+ cast::transmute(raw::Slice { data: self.base as *T, len: self.len })
+ }
+ }
+
+ /// View the stored data as a mutable slice.
+ pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
+ unsafe {
+ cast::transmute(raw::Slice { data: self.base as *T, len: self.len })
+ }
+ }
+
+ /// Retrieves an element at a given index, returning `None` if the requested
+ /// index is greater than the length of the vector.
+ pub fn get<'a>(&'a self, ofs: uint) -> Option<&'a T> {
+ if ofs < self.len {
+ Some(unsafe { &*self.base.offset(ofs as int) })
+ } else {
+ None
+ }
+ }
+
+ /// Retrieves a mutable element at a given index, returning `None` if the
+ /// requested index is greater than the length of the vector.
+ pub fn get_mut<'a>(&'a mut self, ofs: uint) -> Option<&'a mut T> {
+ if ofs < self.len {
+ Some(unsafe { &mut *self.base.offset(ofs as int) })
+ } else {
+ None
+ }
+ }
+
+ /// Unwrap the pointer without running the destructor
+ ///
+ /// This method retrieves the underlying pointer, and in the process
+ /// destroys the CVec but without running the destructor. A use case
+ /// would be transferring ownership of the buffer to a C function, as
+ /// in this case you would not want to run the destructor.
+ ///
+ /// Note that if you want to access the underlying pointer without
+ /// cancelling the destructor, you can simply call `transmute` on the return
+ /// value of `get(0)`.
+ pub unsafe fn unwrap(mut self) -> *mut T {
+ self.dtor = None;
+ self.base
+ }
+}
+
+impl<T> Container for CVec<T> {
+ fn len(&self) -> uint { self.len }
+}
+
+#[cfg(test)]
+mod tests {
+ use prelude::*;
+
+ use super::CVec;
+ use libc;
+ use ptr;
+ use rt::global_heap::malloc_raw;
+
+ fn malloc(n: uint) -> CVec<u8> {
+ unsafe {
+ let mem = malloc_raw(n);
+
+ CVec::new_with_dtor(mem as *mut u8, n,
+ proc() { libc::free(mem as *mut libc::c_void); })
+ }
+ }
+
+ #[test]
+ fn test_basic() {
+ let mut cv = malloc(16);
+
+ *cv.get_mut(3).unwrap() = 8;
+ *cv.get_mut(4).unwrap() = 9;
+ assert_eq!(*cv.get(3).unwrap(), 8);
+ assert_eq!(*cv.get(4).unwrap(), 9);
+ assert_eq!(cv.len(), 16);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_fail_at_null() {
+ unsafe {
+ CVec::new(ptr::mut_null::<u8>(), 9);
+ }
+ }
+
+ #[test]
+ fn test_overrun_get() {
+ let cv = malloc(16);
+
+ assert!(cv.get(17).is_none());
+ }
+
+ #[test]
+ fn test_overrun_set() {
+ let mut cv = malloc(16);
+
+ assert!(cv.get_mut(17).is_none());
+ }
+
+ #[test]
+ fn test_unwrap() {
+ unsafe {
+ let cv = CVec::new_with_dtor(1 as *mut int, 0,
+ proc() { fail!("Don't run this destructor!") });
+ let p = cv.unwrap();
+ assert_eq!(p, 1 as *mut int);
+ }
+ }
+
+}
if debug_mem() {
// We do logging here w/o allocation.
- debug!("total boxes annihilated: {}", n_total_boxes);
+ println!("total boxes annihilated: {}", n_total_boxes);
}
}
totalord_impl!(char)
-/// Compares (a1, b1) against (a2, b2), where the a values are more significant.
-pub fn cmp2<A:TotalOrd,B:TotalOrd>(
- a1: &A, b1: &B,
- a2: &A, b2: &B) -> Ordering
-{
- match a1.cmp(a2) {
- Less => Less,
- Greater => Greater,
- Equal => b1.cmp(b2)
- }
-}
-
/**
Return `o1` if it is not `Equal`, otherwise `o2`. Simulates the
lexical ordering on a type `(int, int)`.
}
#[inline]
-pub fn min<T:Ord>(v1: T, v2: T) -> T {
+pub fn min<T: TotalOrd>(v1: T, v2: T) -> T {
if v1 < v2 { v1 } else { v2 }
}
#[inline]
-pub fn max<T:Ord>(v1: T, v2: T) -> T {
+pub fn max<T: TotalOrd>(v1: T, v2: T) -> T {
if v1 > v2 { v1 } else { v2 }
}
assert_eq!(12.cmp(-5), Greater);
}
- #[test]
- fn test_cmp2() {
- assert_eq!(cmp2(1, 2, 3, 4), Less);
- assert_eq!(cmp2(3, 2, 3, 4), Less);
- assert_eq!(cmp2(5, 2, 3, 4), Greater);
- assert_eq!(cmp2(5, 5, 5, 4), Greater);
- }
-
#[test]
fn test_int_totaleq() {
assert!(5.equals(&5));
pub use self::net::udp::UdpStream;
pub use self::pipe::PipeStream;
pub use self::process::{Process, ProcessConfig};
+pub use self::tempfile::TempDir;
pub use self::mem::{MemReader, BufReader, MemWriter, BufWriter};
pub use self::buffered::{BufferedReader, BufferedWriter, BufferedStream,
LineBufferedWriter};
pub use self::comm_adapters::{ChanReader, ChanWriter};
+// this comes first to get the iotest! macro
pub mod test;
+mod buffered;
+mod comm_adapters;
+mod mem;
+mod result;
+mod tempfile;
+pub mod extensions;
pub mod fs;
-
+pub mod net;
pub mod pipe;
-
pub mod process;
-
-pub mod net;
-
-mod mem;
-
+pub mod signal;
pub mod stdio;
-
-mod result;
-
-pub mod extensions;
-
pub mod timer;
-
-mod buffered;
-
-pub mod signal;
-
pub mod util;
-mod comm_adapters;
-
/// The default buffer size for various I/O operations
// libuv recommends 64k buffers to maximize throughput
// https://groups.google.com/forum/#!topic/libuv/oQO1HJAIDdA
let mut buf = [0];
loop {
match self.read(buf) {
- Ok(0) => {
- debug!("read 0 bytes. trying again");
- }
+ Ok(0) => {}
Ok(1) => return Ok(buf[0]),
Ok(_) => unreachable!(),
Err(e) => return Err(e)
rx.recv();
})
+
+ iotest!(fn shutdown_smoke() {
+ use rt::rtio::RtioTcpStream;
+
+ let addr = next_test_ip4();
+ let a = TcpListener::bind(addr).unwrap().listen();
+ spawn(proc() {
+ let mut a = a;
+ let mut c = a.accept().unwrap();
+ assert_eq!(c.read_to_end(), Ok(~[]));
+ c.write([1]).unwrap();
+ });
+
+ let mut s = TcpStream::connect(addr).unwrap();
+ assert!(s.obj.close_write().is_ok());
+ assert!(s.write([1]).is_err());
+ assert_eq!(s.read_to_end(), Ok(~[1]));
+ })
}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Temporary files and directories
+
+use io::fs;
+use io;
+use iter::{Iterator, range};
+use libc;
+use ops::Drop;
+use option::{Option, None, Some};
+use os;
+use path::{Path, GenericPath};
+use result::{Ok, Err};
+use sync::atomics;
+
+/// A wrapper for a path to temporary directory implementing automatic
+/// scope-based deletion.
+pub struct TempDir {
+ priv path: Option<Path>
+}
+
+impl TempDir {
+ /// Attempts to make a temporary directory inside of `tmpdir` whose name
+ /// will have the suffix `suffix`. The directory will be automatically
+ /// deleted once the returned wrapper is destroyed.
+ ///
+ /// If no directory can be created, None is returned.
+ pub fn new_in(tmpdir: &Path, suffix: &str) -> Option<TempDir> {
+ if !tmpdir.is_absolute() {
+ return TempDir::new_in(&os::make_absolute(tmpdir), suffix);
+ }
+
+ static mut CNT: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
+
+ for _ in range(0u, 1000) {
+ let filename = format!("rs-{}-{}-{}",
+ unsafe { libc::getpid() },
+ unsafe { CNT.fetch_add(1, atomics::SeqCst) },
+ suffix);
+ let p = tmpdir.join(filename);
+ match fs::mkdir(&p, io::UserRWX) {
+ Err(..) => {}
+ Ok(()) => return Some(TempDir { path: Some(p) })
+ }
+ }
+ None
+ }
+
+ /// Attempts to make a temporary directory inside of `os::tmpdir()` whose
+ /// name will have the suffix `suffix`. The directory will be automatically
+ /// deleted once the returned wrapper is destroyed.
+ ///
+ /// If no directory can be created, None is returned.
+ pub fn new(suffix: &str) -> Option<TempDir> {
+ TempDir::new_in(&os::tmpdir(), suffix)
+ }
+
+ /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper.
+ /// This discards the wrapper so that the automatic deletion of the
+ /// temporary directory is prevented.
+ pub fn unwrap(self) -> Path {
+ let mut tmpdir = self;
+ tmpdir.path.take_unwrap()
+ }
+
+ /// Access the wrapped `std::path::Path` to the temporary directory.
+ pub fn path<'a>(&'a self) -> &'a Path {
+ self.path.get_ref()
+ }
+}
+
+impl Drop for TempDir {
+ fn drop(&mut self) {
+ for path in self.path.iter() {
+ if path.exists() {
+ // FIXME: is failing the right thing to do?
+ fs::rmdir_recursive(path).unwrap();
+ }
+ }
+ }
+}
+
+// the tests for this module need to change the path using change_dir,
+// and this doesn't play nicely with other tests so these unit tests are located
+// in src/test/run-pass/tempfile.rs
if sysctl(&mut mib[0], 2, &mut maxfiles as *mut libc::c_int as *mut libc::c_void, &mut size,
mut_null(), 0) != 0 {
let err = last_os_error();
- error!("raise_fd_limit: error calling sysctl: {}", err);
- return;
+ fail!("raise_fd_limit: error calling sysctl: {}", err);
}
// Fetch the current resource limits
let mut rlim = rlimit{rlim_cur: 0, rlim_max: 0};
if getrlimit(RLIMIT_NOFILE, &mut rlim) != 0 {
let err = last_os_error();
- error!("raise_fd_limit: error calling getrlimit: {}", err);
- return;
+ fail!("raise_fd_limit: error calling getrlimit: {}", err);
}
// Bump the soft limit to the smaller of kern.maxfilesperproc and the hard limit
// Set our newly-increased resource limit
if setrlimit(RLIMIT_NOFILE, &rlim) != 0 {
let err = last_os_error();
- error!("raise_fd_limit: error calling setrlimit: {}", err);
- return;
+ fail!("raise_fd_limit: error calling setrlimit: {}", err);
}
}
}
use num::{Zero, One, CheckedAdd, CheckedSub, Saturating, ToPrimitive, Int};
use option::{Option, Some, None};
use ops::{Add, Mul, Sub};
-use cmp::{Eq, Ord};
+use cmp::{Eq, Ord, TotalOrd};
use clone::Clone;
use uint;
use mem;
/// let xs = [1u, 4, 2, 3, 8, 9, 6];
/// let sum = xs.iter()
/// .map(|&x| x)
- /// .inspect(|&x| debug!("filtering {}", x))
+ /// .inspect(|&x| println!("filtering {}", x))
/// .filter(|&x| x % 2 == 0)
- /// .inspect(|&x| debug!("{} made it through", x))
+ /// .inspect(|&x| println!("{} made it through", x))
/// .sum();
/// println!("{}", sum);
/// ```
/// assert_eq!(*xs.iter().max_by(|x| x.abs()).unwrap(), -10);
/// ```
#[inline]
- fn max_by<B: Ord>(&mut self, f: |&A| -> B) -> Option<A> {
+ fn max_by<B: TotalOrd>(&mut self, f: |&A| -> B) -> Option<A> {
self.fold(None, |max: Option<(A, B)>, x| {
let x_val = f(&x);
match max {
/// assert_eq!(*xs.iter().min_by(|x| x.abs()).unwrap(), 0);
/// ```
#[inline]
- fn min_by<B: Ord>(&mut self, f: |&A| -> B) -> Option<A> {
+ fn min_by<B: TotalOrd>(&mut self, f: |&A| -> B) -> Option<A> {
self.fold(None, |min: Option<(A, B)>, x| {
let x_val = f(&x);
match min {
fn min_max(&mut self) -> MinMaxResult<A>;
}
-impl<A: Ord, T: Iterator<A>> OrdIterator<A> for T {
+impl<A: TotalOrd, T: Iterator<A>> OrdIterator<A> for T {
#[inline]
fn max(&mut self) -> Option<A> {
self.fold(None, |max, x| {
html_root_url = "http://static.rust-lang.org/doc/master")];
#[feature(macro_rules, globs, asm, managed_boxes, thread_local, link_args,
- simd, linkage, default_type_params)];
+ simd, linkage, default_type_params, phase)];
// NOTE remove the following two attributes after the next snapshot.
#[allow(unrecognized_lint)];
#[deny(non_camel_case_types)];
#[deny(missing_doc)];
#[allow(unknown_features)];
+#[allow(deprecated_owned_vector)];
// When testing libstd, bring in libuv as the I/O backend so tests can print
// things and all of the std::io tests have an I/O interface to run on top
#[cfg(test)] extern crate rustuv;
#[cfg(test)] extern crate native;
#[cfg(test)] extern crate green;
+#[cfg(test)] #[phase(syntax, link)] extern crate log;
-// Make extra and rand accessible for benchmarking/testcases
+// Make and rand accessible for benchmarking/testcases
#[cfg(test)] extern crate rand;
-#[cfg(test)] extern crate extra = "extra";
// Make std testable by not duplicating lang items. See #2912
#[cfg(test)] extern crate realstd = "std";
#[unstable]
pub mod libc;
pub mod c_str;
+pub mod c_vec;
pub mod os;
pub mod io;
pub mod path;
pub mod cast;
pub mod fmt;
pub mod cleanup;
-pub mod logging;
pub mod mem;
pub use io;
pub use kinds;
pub use local_data;
- pub use logging;
pub use option;
pub use os;
pub use rt;
pub static SO_KEEPALIVE: c_int = 8;
pub static SO_BROADCAST: c_int = 32;
pub static SO_REUSEADDR: c_int = 4;
+
+ pub static SHUT_RD: c_int = 0;
+ pub static SHUT_WR: c_int = 1;
+ pub static SHUT_RDWR: c_int = 2;
}
pub mod extra {
use libc::types::os::arch::c95::c_int;
pub static MAP_SHARED : c_int = 0x0001;
pub static MAP_PRIVATE : c_int = 0x0002;
pub static MAP_FIXED : c_int = 0x0010;
- pub static MAP_ANON : c_int = 0x0020;
+ pub static MAP_ANON : c_int = 0x0800;
pub static MAP_FAILED : *c_void = -1 as *c_void;
pub static SO_KEEPALIVE: c_int = 9;
pub static SO_BROADCAST: c_int = 6;
pub static SO_REUSEADDR: c_int = 2;
+
+ pub static SHUT_RD: c_int = 0;
+ pub static SHUT_WR: c_int = 1;
+ pub static SHUT_RDWR: c_int = 2;
}
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
pub static O_DSYNC : c_int = 16;
pub static O_SYNC : c_int = 16400;
- pub static PROT_GROWSDOWN : c_int = 0x010000000;
- pub static PROT_GROWSUP : c_int = 0x020000000;
+ pub static PROT_GROWSDOWN : c_int = 0x01000000;
+ pub static PROT_GROWSUP : c_int = 0x02000000;
pub static MAP_TYPE : c_int = 0x000f;
- pub static MAP_ANONONYMOUS : c_int = 0x0020;
- pub static MAP_32BIT : c_int = 0x0040;
- pub static MAP_GROWSDOWN : c_int = 0x0100;
- pub static MAP_DENYWRITE : c_int = 0x0800;
- pub static MAP_EXECUTABLE : c_int = 0x01000;
- pub static MAP_LOCKED : c_int = 0x02000;
- pub static MAP_NONRESERVE : c_int = 0x04000;
- pub static MAP_POPULATE : c_int = 0x08000;
- pub static MAP_NONBLOCK : c_int = 0x010000;
- pub static MAP_STACK : c_int = 0x020000;
+ pub static MAP_ANONONYMOUS : c_int = 0x0800;
+ pub static MAP_GROWSDOWN : c_int = 0x01000;
+ pub static MAP_DENYWRITE : c_int = 0x02000;
+ pub static MAP_EXECUTABLE : c_int = 0x04000;
+ pub static MAP_LOCKED : c_int = 0x08000;
+ pub static MAP_NONRESERVE : c_int = 0x0400;
+ pub static MAP_POPULATE : c_int = 0x010000;
+ pub static MAP_NONBLOCK : c_int = 0x020000;
+ pub static MAP_STACK : c_int = 0x040000;
}
#[cfg(target_os = "linux")]
pub mod sysconf {
pub static SO_KEEPALIVE: c_int = 0x0008;
pub static SO_BROADCAST: c_int = 0x0020;
pub static SO_REUSEADDR: c_int = 0x0004;
+
+ pub static SHUT_RD: c_int = 0;
+ pub static SHUT_WR: c_int = 1;
+ pub static SHUT_RDWR: c_int = 2;
}
pub mod extra {
use libc::types::os::arch::c95::c_int;
pub static SO_KEEPALIVE: c_int = 0x0008;
pub static SO_BROADCAST: c_int = 0x0020;
pub static SO_REUSEADDR: c_int = 0x0004;
+
+ pub static SHUT_RD: c_int = 0;
+ pub static SHUT_WR: c_int = 1;
+ pub static SHUT_RDWR: c_int = 2;
}
pub mod extra {
use libc::types::os::arch::c95::c_int;
pub fn sendto(socket: c_int, buf: *c_void, len: size_t,
flags: c_int, addr: *sockaddr,
addrlen: socklen_t) -> ssize_t;
+ pub fn shutdown(socket: c_int, how: c_int) -> c_int;
}
}
pub fn sendto(socket: SOCKET, buf: *c_void, len: c_int,
flags: c_int, addr: *sockaddr,
addrlen: c_int) -> c_int;
+ pub fn shutdown(socket: SOCKET, how: c_int) -> c_int;
}
}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
-
-Utilities for program-wide and customizable logging
-
-This module is used by the compiler when emitting output for the logging family
-of macros. The methods of this module shouldn't necessarily be used directly,
-but rather through the logging macros defined.
-
-There are five macros that the logging subsystem uses:
-
-* `log!(level, ...)` - the generic logging macro, takes a level as a u32 and any
- related `format!` arguments
-* `debug!(...)` - a macro hard-wired to the log level of `DEBUG`
-* `info!(...)` - a macro hard-wired to the log level of `INFO`
-* `warn!(...)` - a macro hard-wired to the log level of `WARN`
-* `error!(...)` - a macro hard-wired to the log level of `ERROR`
-
-All of these macros use the same style of syntax as the `format!` syntax
-extension. Details about the syntax can be found in the documentation of
-`std::fmt` along with the Rust tutorial/manual.
-
-If you want to check at runtime if a given logging level is enabled (e.g. if the
-information you would want to log is expensive to produce), you can use the
-following macro:
-
-* `log_enabled!(level)` - returns true if logging of the given level is enabled
-
-## Enabling logging
-
-Log levels are controlled on a per-module basis, and by default all logging is
-disabled except for `error!` (a log level of 1). Logging is controlled via the
-`RUST_LOG` environment variable. The value of this environment variable is a
-comma-separated list of logging directives. A logging directive is of the form:
-
-```ignore
-path::to::module=log_level
-```
-
-The path to the module is rooted in the name of the crate it was compiled for,
-so if your program is contained in a file `hello.rs`, for example, to turn on
-logging for this file you would use a value of `RUST_LOG=hello`. Furthermore,
-this path is a prefix-search, so all modules nested in the specified module will
-also have logging enabled.
-
-The actual `log_level` is optional to specify. If omitted, all logging will be
-enabled. If specified, the it must be either a numeric in the range of 1-255, or
-it must be one of the strings `debug`, `error`, `info`, or `warn`. If a numeric
-is specified, then all logging less than or equal to that numeral is enabled.
-For example, if logging level 3 is active, error, warn, and info logs will be
-printed, but debug will be omitted.
-
-As the log level for a module is optional, the module to enable logging for is
-also optional. If only a `log_level` is provided, then the global log level for
-all modules is set to this value.
-
-Some examples of valid values of `RUST_LOG` are:
-
-```ignore
-hello // turns on all logging for the 'hello' module
-info // turns on all info logging
-hello=debug // turns on debug logging for 'hello'
-hello=3 // turns on info logging for 'hello'
-hello,std::option // turns on hello, and std's option logging
-error,hello=warn // turn on global error logging and also warn for hello
-```
-
-## Performance and Side Effects
-
-Each of these macros will expand to code similar to:
-
-```rust,ignore
-if log_level <= my_module_log_level() {
- ::std::logging::log(log_level, format!(...));
-}
-```
-
-What this means is that each of these macros are very cheap at runtime if
-they're turned off (just a load and an integer comparison). This also means that
-if logging is disabled, none of the components of the log will be executed.
-
-## Useful Values
-
-For convenience, if a value of `::help` is set for `RUST_LOG`, a program will
-start, print out all modules registered for logging, and then exit.
-
-*/
-
-use fmt;
-use io::LineBufferedWriter;
-use io;
-use io::Writer;
-use mem::replace;
-use ops::Drop;
-use option::{Some, None, Option};
-use prelude::drop;
-use result::{Ok, Err};
-use rt::local::Local;
-use rt::task::Task;
-
-/// Debug log level
-pub static DEBUG: u32 = 4;
-/// Info log level
-pub static INFO: u32 = 3;
-/// Warn log level
-pub static WARN: u32 = 2;
-/// Error log level
-pub static ERROR: u32 = 1;
-
-/// A trait used to represent an interface to a task-local logger. Each task
-/// can have its own custom logger which can respond to logging messages
-/// however it likes.
-pub trait Logger {
- /// Logs a single message described by the `args` structure. The level is
- /// provided in case you want to do things like color the message, etc.
- fn log(&mut self, level: u32, args: &fmt::Arguments);
-}
-
-struct DefaultLogger {
- handle: LineBufferedWriter<io::stdio::StdWriter>,
-}
-
-impl Logger for DefaultLogger {
- // by default, just ignore the level
- fn log(&mut self, _level: u32, args: &fmt::Arguments) {
- match fmt::writeln(&mut self.handle, args) {
- Err(e) => fail!("failed to log: {}", e),
- Ok(()) => {}
- }
- }
-}
-
-impl Drop for DefaultLogger {
- fn drop(&mut self) {
- match self.handle.flush() {
- Err(e) => fail!("failed to flush a logger: {}", e),
- Ok(()) => {}
- }
- }
-}
-
-/// This function is called directly by the compiler when using the logging
-/// macros. This function does not take into account whether the log level
-/// specified is active or not, it will always log something if this method is
-/// called.
-///
-/// It is not recommended to call this function directly, rather it should be
-/// invoked through the logging family of macros.
-pub fn log(level: u32, args: &fmt::Arguments) {
- // See io::stdio::with_task_stdout for why there's a few dances here. The
- // gist of it is that arbitrary code can run during logging (and set an
- // arbitrary logging handle into the task) so we need to be careful that the
- // local task is in TLS while we're running arbitrary code.
- let mut logger = {
- let mut task = Local::borrow(None::<Task>);
- task.get().logger.take()
- };
-
- if logger.is_none() {
- logger = Some(~DefaultLogger { handle: io::stderr(), } as ~Logger);
- }
- logger.get_mut_ref().log(level, args);
-
- let mut task = Local::borrow(None::<Task>);
- let prev = replace(&mut task.get().logger, logger);
- drop(task);
- drop(prev);
-}
-
-/// Replaces the task-local logger with the specified logger, returning the old
-/// logger.
-pub fn set_logger(logger: ~Logger) -> Option<~Logger> {
- let mut task = Local::borrow(None::<Task>);
- replace(&mut task.get().logger, Some(logger))
-}
#[macro_escape];
-/// The standard logging macro
-///
-/// This macro will generically log over a provided level (of type u32) with a
-/// format!-based argument list. See documentation in `std::fmt` for details on
-/// how to use the syntax, and documentation in `std::logging` for info about
-/// logging macros.
-///
-/// # Example
-///
-/// ```
-/// log!(::std::logging::DEBUG, "this is a debug message");
-/// log!(::std::logging::WARN, "this is a warning {}", "message");
-/// log!(6, "this is a custom logging level: {level}", level=6);
-/// ```
-#[macro_export]
-macro_rules! log(
- ($lvl:expr, $($arg:tt)+) => ({
- let lvl = $lvl;
- if lvl <= __log_level() {
- format_args!(|args| {
- ::std::logging::log(lvl, args)
- }, $($arg)+)
- }
- })
-)
-
-/// A convenience macro for logging at the error log level. See `std::logging`
-/// for more information. about logging.
-///
-/// # Example
-///
-/// ```
-/// # let error = 3;
-/// error!("the build has failed with error code: {}", error);
-/// ```
-#[macro_export]
-macro_rules! error(
- ($($arg:tt)*) => (log!(1u32, $($arg)*))
-)
-
-/// A convenience macro for logging at the warning log level. See `std::logging`
-/// for more information. about logging.
-///
-/// # Example
-///
-/// ```
-/// # let code = 3;
-/// warn!("you may like to know that a process exited with: {}", code);
-/// ```
-#[macro_export]
-macro_rules! warn(
- ($($arg:tt)*) => (log!(2u32, $($arg)*))
-)
-
-/// A convenience macro for logging at the info log level. See `std::logging`
-/// for more information. about logging.
-///
-/// # Example
-///
-/// ```
-/// # let ret = 3;
-/// info!("this function is about to return: {}", ret);
-/// ```
-#[macro_export]
-macro_rules! info(
- ($($arg:tt)*) => (log!(3u32, $($arg)*))
-)
-
-/// A convenience macro for logging at the debug log level. See `std::logging`
-/// for more information. about logging.
-///
-/// # Example
-///
-/// ```
-/// debug!("x = {x}, y = {y}", x=10, y=20);
-/// ```
-#[macro_export]
-macro_rules! debug(
- ($($arg:tt)*) => (if cfg!(not(ndebug)) { log!(4u32, $($arg)*) })
-)
-
-/// A macro to test whether a log level is enabled for the current module.
-///
-/// # Example
-///
-/// ```
-/// # struct Point { x: int, y: int }
-/// # fn some_expensive_computation() -> Point { Point { x: 1, y: 2 } }
-/// if log_enabled!(std::logging::DEBUG) {
-/// let x = some_expensive_computation();
-/// debug!("x.x = {}, x.y = {}", x.x, x.y);
-/// }
-/// ```
-#[macro_export]
-macro_rules! log_enabled(
- ($lvl:expr) => ({
- let lvl = $lvl;
- lvl <= __log_level() && (lvl != 4 || cfg!(not(ndebug)))
- })
-)
-
/// The entry point for failure of rust tasks.
///
/// This macro is used to inject failure into a rust task, causing the task to
{ unreachable!() }
})
}
+
+// When testing the standard library, we link to the liblog crate to get the
+// logging macros. In doing so, the liblog crate was linked against the real
+// version of libstd, and uses a different std::fmt module than the test crate
+// uses. To get around this difference, we redefine the log!() macro here to be
+// just a dumb version of what it should be.
+#[cfg(test)]
+macro_rules! log (
+ ($lvl:expr, $($args:tt)*) => (
+ if log_enabled!($lvl) { println!($($args)*) }
+ )
+)
}
}
- /// Convert from `Option<T>` to `&[T]` (without copying)
+ /// Convert from `Option<T>` to `&mut [T]` (without copying)
#[inline]
pub fn as_mut_slice<'r>(&'r mut self) -> &'r mut [T] {
match *self {
/// Return an iterator over the possibly contained value
#[inline]
pub fn iter<'r>(&'r self) -> Item<&'r T> {
- match *self {
- Some(ref x) => Item{opt: Some(x)},
- None => Item{opt: None}
- }
+ Item{opt: self.as_ref()}
}
/// Return a mutable iterator over the possibly contained value
#[inline]
pub fn mut_iter<'r>(&'r mut self) -> Item<&'r mut T> {
- match *self {
- Some(ref mut x) => Item{opt: Some(x)},
- None => Item{opt: None}
- }
+ Item{opt: self.as_mut()}
}
/// Return a consuming iterator over the possibly contained value
/// Applies a function zero or more times until the result is `None`.
#[inline]
- pub fn while_some(self, blk: |v: T| -> Option<T>) {
+ pub fn while_some(self, f: |v: T| -> Option<T>) {
let mut opt = self;
- while opt.is_some() {
- opt = blk(opt.unwrap());
+ loop {
+ match opt {
+ Some(x) => opt = f(x),
+ None => break
+ }
}
}
/// Fails if the value equals `None`.
#[inline]
pub fn take_unwrap(&mut self) -> T {
- if self.is_none() {
- fail!("called `Option::take_unwrap()` on a `None` value")
+ match self.take() {
+ Some(x) => x,
+ None => fail!("called `Option::take_unwrap()` on a `None` value")
}
- self.take().unwrap()
}
/// Gets an immutable reference to the value inside an option.
if self.len == 0 { /* workaround for dummy_stack */ return; }
unsafe {
- match libc::munmap(self.data as *c_void, self.len as libc::size_t) {
- 0 => (),
- -1 => match errno() as c_int {
- libc::EINVAL => error!("invalid addr or len"),
- e => error!("unknown errno={}", e)
- },
- r => error!("Unexpected result {}", r)
- }
+ // FIXME: what to do if this fails?
+ let _ = libc::munmap(self.data as *c_void, self.len as libc::size_t);
}
}
}
MapAddr(addr_) => { lpAddress = addr_ as LPVOID; },
MapFd(fd_) => { fd = fd_; },
MapOffset(offset_) => { offset = offset_; },
- MapNonStandardFlags(f) => {
- info!("MemoryMap::new: MapNonStandardFlags used on \
- Windows: {}", f)
- }
+ MapNonStandardFlags(..) => {}
}
}
MapVirtual => {
if libc::VirtualFree(self.data as *mut c_void, 0,
libc::MEM_RELEASE) == 0 {
- error!("VirtualFree failed: {}", errno());
+ println!("VirtualFree failed: {}", errno());
}
},
MapFile(mapping) => {
if libc::UnmapViewOfFile(self.data as LPCVOID) == FALSE {
- error!("UnmapViewOfFile failed: {}", errno());
+ println!("UnmapViewOfFile failed: {}", errno());
}
if libc::CloseHandle(mapping as HANDLE) == FALSE {
- error!("CloseHandle failed: {}", errno());
+ println!("CloseHandle failed: {}", errno());
}
}
}
use rand::Rng;
use rand;
-
#[test]
pub fn last_os_error() {
debug!("{}", os::last_os_error());
SAFETY NOTE: Pointer-arithmetic. Dragons be here.
*/
pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: |*T|) {
- debug!("array_each_with_len: before iterate");
if arr.is_null() {
fail!("ptr::array_each_with_len failure: arr input is null pointer");
}
let n = arr.offset(e as int);
cb(*n);
}
- debug!("array_each_with_len: after iterate");
}
/**
fail!("ptr::array_each_with_len failure: arr input is null pointer");
}
let len = buf_len(arr);
- debug!("array_each inferred len: {}", len);
array_each_with_len(arr, len, cb);
}
use io::{IoResult, Writer};
use iter::Iterator;
use option::{Some, None};
+use os;
use result::{Ok, Err};
use str::StrSlice;
+use sync::atomics;
pub use self::imp::write;
-// This function is defined in this module so that the way to enable logging of
-// backtraces has the word 'backtrace' in it: std::rt::backtrace.
+// For now logging is turned off by default, and this function checks to see
+// whether the magical environment variable is present to see if it's turned on.
pub fn log_enabled() -> bool {
- log_enabled!(::logging::DEBUG)
+ static mut ENABLED: atomics::AtomicInt = atomics::INIT_ATOMIC_INT;
+ unsafe {
+ match ENABLED.load(atomics::SeqCst) {
+ 1 => return false,
+ 2 => return true,
+ _ => {}
+ }
+ }
+
+ let val = match os::getenv("RUST_BACKTRACE") {
+ Some(..) => 2,
+ None => 1,
+ };
+ unsafe { ENABLED.store(val, atomics::SeqCst); }
+ val == 2
}
#[cfg(target_word_size = "64")] static HEX_WIDTH: uint = 18;
rest = rest.slice_from(1);
}
let i: uint = from_str(s.slice_to(s.len() - rest.len())).unwrap();
- try!(writer.write_str(rest.slice_to(i)));
s = rest.slice_from(i);
+ rest = rest.slice_to(i);
+ loop {
+ if rest.starts_with("$") {
+ macro_rules! demangle(
+ ($($pat:expr => $demangled:expr),*) => ({
+ $(if rest.starts_with($pat) {
+ try!(writer.write_str($demangled));
+ rest = rest.slice_from($pat.len());
+ } else)*
+ {
+ try!(writer.write_str(rest));
+ break;
+ }
+
+ })
+ )
+ // see src/librustc/back/link.rs for these mappings
+ demangle! (
+ "$SP$" => "@",
+ "$UP$" => "~",
+ "$RP$" => "*",
+ "$BP$" => "&",
+ "$LT$" => "<",
+ "$GT$" => ">",
+ "$LP$" => "(",
+ "$RP$" => ")",
+ "$C$" => ",",
+
+ // in theory we can demangle any unicode code point, but
+ // for simplicity we just catch the common ones.
+ "$x20" => " ",
+ "$x27" => "'",
+ "$x5b" => "[",
+ "$x5d" => "]"
+ )
+ } else {
+ try!(writer.write_str(rest));
+ break;
+ }
+ }
}
}
use io::MemWriter;
use str;
+ macro_rules! t( ($a:expr, $b:expr) => ({
+ let mut m = MemWriter::new();
+ super::demangle(&mut m, $a).unwrap();
+ assert_eq!(str::from_utf8_owned(m.unwrap()).unwrap(), $b.to_owned());
+ }) )
+
#[test]
fn demangle() {
- macro_rules! t( ($a:expr, $b:expr) => ({
- let mut m = MemWriter::new();
- super::demangle(&mut m, $a);
- assert_eq!(str::from_utf8_owned(m.unwrap()).unwrap(), $b.to_owned());
- }) )
-
t!("test", "test");
t!("_ZN4testE", "test");
t!("_ZN4test", "_ZN4test");
t!("_ZN4test1a2bcE", "test::a::bc");
}
+
+ #[test]
+ fn demangle_dollars() {
+ t!("_ZN4$UP$E", "~");
+ t!("_ZN8$UP$testE", "~test");
+ t!("_ZN8$UP$test4foobE", "~test::foob");
+ t!("_ZN8$x20test4foobE", " test::foob");
+ }
}
// except according to those terms.
use cast;
-use cmp::TotalOrd;
-use container::MutableSet;
-use iter::Iterator;
use option::{Some, None, Option};
use ptr::RawPtr;
use rt::rtio::EventLoop;
-use vec::{ImmutableVector, OwnedVector};
+
+#[cfg(stage0)] use cmp::TotalOrd;
+#[cfg(stage0)] use container::MutableSet;
+#[cfg(stage0)] use iter::Iterator;
+#[cfg(stage0)] use vec::{ImmutableVector, OwnedVector};
// Need to tell the linker on OS X to not barf on undefined symbols
// and instead look them up at runtime, which we need to resolve
#[link_args = "-Wl,-U,__rust_crate_map_toplevel"]
extern {}
+#[cfg(stage0)]
pub struct ModEntry<'a> {
name: &'a str,
log_level: *mut u32
}
+#[cfg(stage0)]
pub struct CrateMap<'a> {
version: i32,
entries: &'a [ModEntry<'a>],
children: &'a [&'a CrateMap<'a>],
event_loop_factory: Option<fn() -> ~EventLoop>,
}
+#[cfg(not(stage0))]
+pub struct CrateMap<'a> {
+ version: i32,
+ event_loop_factory: Option<fn() -> ~EventLoop>,
+}
// When working on android, apparently weak symbols don't work so well for
// finding the crate map, and neither does dlopen + dlsym. This is mainly a
}
}
+#[cfg(stage0)]
fn version(crate_map: &CrateMap) -> i32 {
match crate_map.version {
2 => return 2,
}
}
+#[cfg(stage0)]
fn do_iter_crate_map<'a>(
crate_map: &'a CrateMap<'a>,
f: |&'a ModEntry<'a>|,
}
/// Iterates recursively over `crate_map` and all child crate maps
+#[cfg(stage0)]
pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: |&'a ModEntry<'a>|) {
let mut v = ~[];
do_iter_crate_map(crate_map, f, &mut v);
}
-
-#[cfg(test)]
-mod tests {
- use option::None;
- use rt::crate_map::{CrateMap, ModEntry, iter_crate_map};
-
- #[test]
- fn iter_crate_map_duplicates() {
- let mut level3: u32 = 3;
-
- let entries = [
- ModEntry { name: "c::m1", log_level: &mut level3},
- ];
-
- let child_crate = CrateMap {
- version: 2,
- entries: entries,
- children: &[],
- event_loop_factory: None,
- };
-
- let root_crate = CrateMap {
- version: 2,
- entries: &[],
- children: &[&child_crate, &child_crate],
- event_loop_factory: None,
- };
-
- let mut cnt = 0;
- unsafe {
- iter_crate_map(&root_crate, |entry| {
- assert!(*entry.log_level == 3);
- cnt += 1;
- });
- assert!(cnt == 1);
- }
- }
-
- #[test]
- fn iter_crate_map_follow_children() {
- let mut level2: u32 = 2;
- let mut level3: u32 = 3;
- let child_crate2 = CrateMap {
- version: 2,
- entries: &[
- ModEntry { name: "c::m1", log_level: &mut level2},
- ModEntry { name: "c::m2", log_level: &mut level3},
- ],
- children: &[],
- event_loop_factory: None,
- };
-
- let child_crate1 = CrateMap {
- version: 2,
- entries: &[
- ModEntry { name: "t::f1", log_level: &mut 1},
- ],
- children: &[&child_crate2],
- event_loop_factory: None,
- };
-
- let root_crate = CrateMap {
- version: 2,
- entries: &[
- ModEntry { name: "t::f2", log_level: &mut 0},
- ],
- children: &[&child_crate1],
- event_loop_factory: None,
- };
-
- let mut cnt = 0;
- unsafe {
- iter_crate_map(&root_crate, |entry| {
- assert!(*entry.log_level == cnt);
- cnt += 1;
- });
- assert!(cnt == 4);
- }
- }
-}
#[cfg(target_arch = "arm")]
pub static unwinder_private_data_size: int = 20;
+#[cfg(target_arch = "mips")]
+pub static unwinder_private_data_size: int = 2;
+
pub struct _Unwind_Exception {
exception_class: _Unwind_Exception_Class,
exception_cleanup: _Unwind_Exception_Cleanup_Fn,
pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
trace_argument: *libc::c_void)
-> _Unwind_Reason_Code;
- #[cfg(not(target_os = "android"))]
+ #[cfg(stage0, not(target_os = "android"))]
+ pub fn _Unwind_GetIP(ctx: *_Unwind_Context) -> libc::uintptr_t;
+ #[cfg(stage0, not(target_os = "android"))]
+ pub fn _Unwind_FindEnclosingFunction(pc: *libc::c_void) -> *libc::c_void;
+
+ #[cfg(not(stage0),
+ not(target_os = "android"),
+ not(target_os = "linux", target_arch = "arm"))]
pub fn _Unwind_GetIP(ctx: *_Unwind_Context) -> libc::uintptr_t;
- #[cfg(not(target_os = "android"))]
+ #[cfg(not(stage0),
+ not(target_os = "android"),
+ not(target_os = "linux", target_arch = "arm"))]
pub fn _Unwind_FindEnclosingFunction(pc: *libc::c_void) -> *libc::c_void;
}
// of the macro. This is all copy/pasted directly from the header file with the
// definition of _Unwind_GetIP.
#[cfg(target_os = "android")]
+#[cfg(target_os = "linux", target_arch = "arm")]
pub unsafe fn _Unwind_GetIP(ctx: *_Unwind_Context) -> libc::uintptr_t {
#[repr(C)]
enum _Unwind_VRS_Result {
(val & !1) as libc::uintptr_t
}
-// This function also doesn't exist on android, so make it a no-op
+// This function also doesn't exist on android or arm/linux, so make it a no-op
#[cfg(target_os = "android")]
-pub unsafe fn _Unwind_FindEnclosingFunction(pc: *libc::c_void) -> *libc::c_void{
+#[cfg(target_os = "linux", target_arch = "arm")]
+pub unsafe fn _Unwind_FindEnclosingFunction(pc: *libc::c_void) -> *libc::c_void {
pc
}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use container::Container;
-use from_str::from_str;
-use iter::Iterator;
-use libc::exit;
-use option::{Some, None, Option};
-use os;
-use rt::crate_map::{ModEntry, CrateMap, iter_crate_map, get_crate_map};
-use str::{Str, StrSlice};
-use vec::{ImmutableVector, MutableTotalOrdVector, OwnedVector};
-use vec_ng::Vec;
-
-struct LogDirective<'a> {
- name: Option<&'a str>,
- level: u32
-}
-
-static MAX_LOG_LEVEL: u32 = 255;
-static DEFAULT_LOG_LEVEL: u32 = 1;
-static log_level_names : &'static[&'static str] = &'static["error", "warn", "info", "debug"];
-
-/// Parse an individual log level that is either a number or a symbolic log level
-fn parse_log_level(level: &str) -> Option<u32> {
- let num = from_str::<u32>(level);
- let mut log_level;
- match num {
- Some(num) => {
- if num < MAX_LOG_LEVEL {
- log_level = Some(num);
- } else {
- log_level = Some(MAX_LOG_LEVEL);
- }
- }
- _ => {
- let position = log_level_names.iter().position(|&name| name == level);
- match position {
- Some(position) => {
- log_level = Some(::cmp::min(MAX_LOG_LEVEL, (position + 1) as u32))
- },
- _ => {
- log_level = None;
- }
- }
- }
- }
- log_level
-}
-
-/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1")
-/// and return a vector with log directives.
-/// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in std::).
-/// Also supports string log levels of error, warn, info, and debug
-fn parse_logging_spec<'a>(spec: &'a str) -> Vec<LogDirective<'a>> {
- let mut dirs = Vec::new();
- for s in spec.split(',') {
- if s.len() == 0 { continue }
- let mut parts = s.split('=');
- let log_level;
- let name;
- match (parts.next(), parts.next(), parts.next()) {
- (Some(part0), None, None) => {
- //if the single argument is a log-level string or number,
- //treat that as a global fallback
- let possible_log_level = parse_log_level(part0);
- match possible_log_level {
- Some(num) => {
- name = None;
- log_level = num;
- },
- None => {
- log_level = MAX_LOG_LEVEL;
- name = Some(part0);
- }
- }
- }
- (Some(part0), Some(part1), None) => {
- let possible_log_level = parse_log_level(part1);
- match possible_log_level {
- Some(num) => {
- name = Some(part0);
- log_level = num;
- },
- _ => {
- rterrln!("warning: invalid logging spec '{}', \
- ignoring it", part1);
- continue
- }
- }
- },
- _ => {
- rterrln!("warning: invalid logging spec '{}', \
- ignoring it", s);
- continue
- }
- }
- dirs.push(LogDirective { name: name, level: log_level });
- }
- return dirs;
-}
-
-/// Set the log level of an entry in the crate map depending on the vector
-/// of log directives
-fn update_entry(dirs: &[LogDirective], entry: &ModEntry) -> u32 {
- let mut new_lvl: u32 = DEFAULT_LOG_LEVEL;
- let mut longest_match = -1i;
- for dir in dirs.iter() {
- match dir.name {
- None => {
- if longest_match == -1 {
- longest_match = 0;
- new_lvl = dir.level;
- }
- }
- Some(ref dir_name) => {
- let name = entry.name;
- let len = dir_name.len() as int;
- if name.starts_with(*dir_name) &&
- len >= longest_match {
- longest_match = len;
- new_lvl = dir.level;
- }
- }
- };
- }
- unsafe { *entry.log_level = new_lvl; }
- if longest_match >= 0 { return 1; } else { return 0; }
-}
-
-/// Set log level for every entry in crate_map according to the sepecification
-/// in settings
-fn update_log_settings(crate_map: &CrateMap, settings: &str) {
- if settings == "::help" || settings == "?" {
- rterrln!("\nCrate log map:\n");
-
- let mut entries = Vec::new();
- iter_crate_map(crate_map, |entry| entries.push(entry.name));
- entries.as_mut_slice().sort();
-
- for name in entries.iter() {
- rterrln!(" {}", *name);
- }
- unsafe { exit(1); }
- }
- let dirs = parse_logging_spec(settings);
-
- let mut n_matches: u32 = 0;
- iter_crate_map(crate_map, |entry| {
- let m = update_entry(dirs.as_slice(), entry);
- n_matches += m;
- });
-
- if n_matches < (dirs.len() as u32) {
- rterrln!("warning: got {} RUST_LOG specs but only matched\n\
- {} of them. You may have mistyped a RUST_LOG spec. \n\
- Use RUST_LOG=::help to see the list of crates and modules.\n",
- dirs.len(), n_matches);
- }
-}
-
-/// Configure logging by traversing the crate map and setting the
-/// per-module global logging flags based on the logging spec
-pub fn init() {
- let log_spec = os::getenv("RUST_LOG");
- match get_crate_map() {
- Some(crate_map) => {
- match log_spec {
- Some(spec) => update_log_settings(crate_map, spec.as_slice()),
- None => update_log_settings(crate_map, ""),
- }
- },
- _ => {
- match log_spec {
- Some(_) => {
- rterrln!("warning: RUST_LOG set, but no crate map found.");
- },
- None => {}
- }
- }
- }
-}
-
-// Tests for parse_logging_spec()
-#[test]
-fn parse_logging_spec_valid() {
- let dirs = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4");
- let dirs = dirs.as_slice();
- assert_eq!(dirs.len(), 3);
- assert_eq!(dirs[0].name, Some("crate1::mod1"));
- assert_eq!(dirs[0].level, 1);
-
- assert_eq!(dirs[1].name, Some("crate1::mod2"));
- assert_eq!(dirs[1].level, MAX_LOG_LEVEL);
-
- assert_eq!(dirs[2].name, Some("crate2"));
- assert_eq!(dirs[2].level, 4);
-}
-
-#[test]
-fn parse_logging_spec_invalid_crate() {
- // test parse_logging_spec with multiple = in specification
- let dirs = parse_logging_spec("crate1::mod1=1=2,crate2=4");
- let dirs = dirs.as_slice();
- assert_eq!(dirs.len(), 1);
- assert_eq!(dirs[0].name, Some("crate2"));
- assert_eq!(dirs[0].level, 4);
-}
-
-#[test]
-fn parse_logging_spec_invalid_log_level() {
- // test parse_logging_spec with 'noNumber' as log level
- let dirs = parse_logging_spec("crate1::mod1=noNumber,crate2=4");
- let dirs = dirs.as_slice();
- assert_eq!(dirs.len(), 1);
- assert_eq!(dirs[0].name, Some("crate2"));
- assert_eq!(dirs[0].level, 4);
-}
-
-#[test]
-fn parse_logging_spec_string_log_level() {
- // test parse_logging_spec with 'warn' as log level
- let dirs = parse_logging_spec("crate1::mod1=wrong,crate2=warn");
- let dirs = dirs.as_slice();
- assert_eq!(dirs.len(), 1);
- assert_eq!(dirs[0].name, Some("crate2"));
- assert_eq!(dirs[0].level, 2);
-}
-
-#[test]
-fn parse_logging_spec_global() {
- // test parse_logging_spec with no crate
- let dirs = parse_logging_spec("warn,crate2=4");
- let dirs = dirs.as_slice();
- assert_eq!(dirs.len(), 2);
- assert_eq!(dirs[0].name, None);
- assert_eq!(dirs[0].level, 2);
- assert_eq!(dirs[1].name, Some("crate2"));
- assert_eq!(dirs[1].level, 4);
-}
-
-// Tests for update_entry
-#[test]
-fn update_entry_match_full_path() {
- let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 },
- LogDirective { name: Some("crate2"), level: 3 }];
- let mut level = 0;
- {
- let entry = &ModEntry { name: "crate1::mod1", log_level: &mut level };
- assert_eq!(update_entry(dirs, entry), 1);
- }
- assert_eq!(level, 2);
-}
-
-#[test]
-fn update_entry_no_match() {
- let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 },
- LogDirective { name: Some("crate2"), level: 3 }];
- let mut level = 0;
- {
- let entry = &ModEntry { name: "crate3::mod1", log_level: &mut level };
- assert_eq!(update_entry(dirs, entry), 0);
- }
- assert_eq!(level, DEFAULT_LOG_LEVEL);
-}
-
-#[test]
-fn update_entry_match_beginning() {
- let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 },
- LogDirective { name: Some("crate2"), level: 3 }];
- let mut level = 0;
- {
- let entry= &ModEntry {name: "crate2::mod1", log_level: &mut level};
- assert_eq!(update_entry(dirs, entry), 1);
- }
- assert_eq!(level, 3);
-}
-
-#[test]
-fn update_entry_match_beginning_longest_match() {
- let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 },
- LogDirective { name: Some("crate2"), level: 3 },
- LogDirective { name: Some("crate2::mod"), level: 4 }];
- let mut level = 0;
- {
- let entry = &ModEntry { name: "crate2::mod1", log_level: &mut level };
- assert_eq!(update_entry(dirs, entry), 1);
- }
- assert_eq!(level, 4);
-}
-
-#[test]
-fn update_entry_match_default() {
- let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 },
- LogDirective { name: None, level: 3 }];
- let mut level = 0;
- {
- let entry = &ModEntry { name: "crate1::mod1", log_level: &mut level };
- assert_eq!(update_entry(dirs, entry), 1);
- }
- assert_eq!(level, 2);
- {
- let entry = &ModEntry { name: "crate2::mod2", log_level: &mut level };
- assert_eq!(update_entry(dirs, entry), 1);
- }
- assert_eq!(level, 3);
-}
/// The local, managed heap
pub mod local_heap;
-/// The Logger trait and implementations
-pub mod logging;
-
/// Crate map
pub mod crate_map;
unsafe {
args::init(argc, argv);
env::init();
- logging::init();
local_ptr::init();
at_exit_imp::init();
}
fn keepalive(&mut self, delay_in_seconds: uint) -> Result<(), IoError>;
fn letdie(&mut self) -> Result<(), IoError>;
fn clone(&self) -> ~RtioTcpStream;
+ fn close_write(&mut self) -> Result<(), IoError>;
}
pub trait RtioSocket {
use io::Writer;
use iter::{Iterator, Take};
use local_data;
-use logging::Logger;
use ops::Drop;
use option::{Option, Some, None};
use prelude::drop;
destroyed: bool,
name: Option<SendStr>,
- logger: Option<~Logger>,
stdout: Option<~Writer>,
stderr: Option<~Writer>,
death: Death::new(),
destroyed: false,
name: None,
- logger: None,
stdout: None,
stderr: None,
imp: None,
#[allow(unused_must_use)]
fn close_outputs() {
let mut task = Local::borrow(None::<Task>);
- let logger = task.get().logger.take();
let stderr = task.get().stderr.take();
let stdout = task.get().stdout.take();
drop(task);
- drop(logger); // loggers are responsible for flushing
match stdout { Some(mut w) => { w.flush(); }, None => {} }
match stderr { Some(mut w) => { w.flush(); }, None => {} }
}
if backtrace::log_enabled() {
let mut err = ::rt::util::Stderr;
let _err = backtrace::write(&mut err);
+ } else {
+ rterrln!("run with `RUST_BACKTRACE=1` to see a backtrace");
}
unsafe { intrinsics::abort() }
}
}
}
+// temporary workaround
+// it causes link failure on MIPS target
+// libgcc doesn't implement 64-bit atomic operations for MIPS32
+#[cfg(not(target_arch = "mips"))]
impl AtomicU64 {
pub fn new(v: u64) -> AtomicU64 {
AtomicU64 { v:v, nopod: marker::NoPod }
use comm::{Sender, Receiver, channel};
use io::Writer;
use kinds::{Send, marker};
-use logging::Logger;
use option::{None, Some, Option};
use result::{Result, Ok, Err};
use rt::local::Local;
name: Option<SendStr>,
/// The size of the stack for the spawned task
stack_size: Option<uint>,
- /// Task-local logger (see std::logging)
- logger: Option<~Logger>,
/// Task-local stdout
stdout: Option<~Writer>,
/// Task-local stderr
notify_chan: None,
name: None,
stack_size: None,
- logger: None,
stdout: None,
stderr: None,
}
static __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
#[cfg(target_arch = "arm")]
static __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
+ #[cfg(target_arch = "mips")]
+ static __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
#[cfg(target_arch = "x86_64")]
static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
#[cfg(target_arch = "x86")]
static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
#[cfg(target_arch = "arm")]
static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
+ #[cfg(target_arch = "mips")]
+ static __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
pub struct pthread_mutex_t {
__align: libc::c_longlong,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// Migrate documentation over from `std::vec` when it is removed.
-#[doc(hidden)];
+// Migrate documentation over from `std::vec` progressively. (This is
+// shown in docs so that people have something to refer too, even if
+// the page is rather empty.)
+#[allow(missing_doc)];
use cast::{forget, transmute};
use clone::Clone;
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
+#[feature(phase)];
+
+#[allow(deprecated_owned_vector)];
+
+#[cfg(test)] #[phase(syntax, link)] extern crate log;
pub use arc::{Arc, MutexArc, RWArc, RWWriteMode, RWReadMode, ArcCondvar, CowArc};
pub use sync::{Mutex, RWLock, Condvar, Semaphore, RWLockWriteMode,
ExprAgain(Option<Ident>),
ExprRet(Option<@Expr>),
- /// Gets the log level for the enclosing module
- ExprLogLevel,
-
ExprInlineAsm(InlineAsm),
ExprMac(Mac),
TyPath(Path, Option<OptVec<TyParamBound>>, NodeId), // for #7264; see above
TyTypeof(@Expr),
// TyInfer means the type should be inferred instead of it having been
- // specified. This should only appear at the "top level" of a type and not
- // nested in one.
+ // specified. This can appear anywhere in a type.
TyInfer,
}
use print::pprust;
use util::small_vector::SmallVector;
-use std::logging;
use std::cell::RefCell;
use std::iter;
use std::vec;
cx.fold_crate(krate)
};
- if log_enabled!(logging::DEBUG) {
+ if log_enabled!(::log::DEBUG) {
let map = map.map.borrow();
// This only makes sense for ordered stores; note the
// enumerate to count the number of entries.
debug!("not!");
// inside #[cfg(not(...))], so these need to all
// not match.
- not_cfgs.iter().all(|mi| {
+ !not_cfgs.iter().all(|mi| {
debug!("cfg(not({}[...]))", mi.name());
- !contains(cfg, *mi)
+ contains(cfg, *mi)
})
}
_ => contains(cfg, *cfg_mi)
use std::iter::range;
use term;
-static BUG_REPORT_URL: &'static str =
- "http://static.rust-lang.org/doc/master/complement-bugreport.html";
// maximum number of lines we will print for each error; arbitrary.
static MAX_LINES: uint = 6u;
/// how a rustc task died (if so desired).
pub struct FatalError;
+/// Signifies that the compiler died with an explicit call to `.bug`
+/// or `.span_bug` rather than a failed assertion, etc.
+pub struct ExplicitBug;
+
// a span-handler is like a handler but also
// accepts span information for source-location
// reporting.
self.handler.custom_emit(&*self.cm, sp, msg, Note);
}
pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
- self.span_fatal(sp, ice_msg(msg));
+ self.handler.emit(Some((&*self.cm, sp)), msg, Bug);
+ fail!(ExplicitBug);
}
pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
self.span_bug(sp, ~"unimplemented " + msg);
self.emit.borrow_mut().get().emit(None, msg, Note);
}
pub fn bug(&self, msg: &str) -> ! {
- self.fatal(ice_msg(msg));
+ self.emit.borrow_mut().get().emit(None, msg, Bug);
+ fail!(ExplicitBug);
}
pub fn unimpl(&self, msg: &str) -> ! {
self.bug(~"unimplemented " + msg);
}
}
-pub fn ice_msg(msg: &str) -> ~str {
- format!("internal compiler error: {}\nThis message reflects a bug in the Rust compiler. \
- \nWe would appreciate a bug report: {}", msg, BUG_REPORT_URL)
-}
-
pub fn mk_span_handler(handler: @Handler, cm: @codemap::CodeMap)
-> @SpanHandler {
@SpanHandler {
#[deriving(Eq)]
pub enum Level {
+ Bug,
Fatal,
Error,
Warning,
use std::fmt::Show;
match *self {
+ Bug => "error: internal compiler error".fmt(f),
Fatal | Error => "error".fmt(f),
Warning => "warning".fmt(f),
Note => "note".fmt(f),
impl Level {
fn color(self) -> term::color::Color {
match self {
- Fatal | Error => term::color::BRIGHT_RED,
+ Bug | Fatal | Error => term::color::BRIGHT_RED,
Warning => term::color::BRIGHT_YELLOW,
Note => term::color::BRIGHT_GREEN
}
Outputs,
Inputs,
Clobbers,
- Options
+ Options,
+ StateNone
}
-fn next_state(s: State) -> Option<State> {
- match s {
- Asm => Some(Outputs),
- Outputs => Some(Inputs),
- Inputs => Some(Clobbers),
- Clobbers => Some(Options),
- Options => None
+impl State {
+ fn next(&self) -> State {
+ match *self {
+ Asm => Outputs,
+ Outputs => Inputs,
+ Inputs => Clobbers,
+ Clobbers => Options,
+ Options => StateNone,
+ StateNone => StateNone
+ }
}
}
+static OPTIONS: &'static [&'static str] = &["volatile", "alignstack", "intel"];
+
pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> base::MacResult {
let mut p = parse::new_parser_from_tts(cx.parse_sess(),
let mut state = Asm;
- // Not using labeled break to get us through one round of bootstrapping.
- let mut continue_ = true;
- while continue_ {
+ let mut read_write_operands = Vec::new();
+
+ 'statement: loop {
match state {
Asm => {
let (s, style) = match expr_to_str(cx, p.parse_expr(),
let (constraint, _str_style) = p.parse_str();
- if constraint.get().starts_with("+") {
- cx.span_unimpl(p.last_span,
- "'+' (read+write) output operand constraint modifier");
- } else if !constraint.get().starts_with("=") {
- cx.span_err(p.last_span, "output operand constraint lacks '='");
- }
+ let span = p.last_span;
p.expect(&token::LPAREN);
let out = p.parse_expr();
p.expect(&token::RPAREN);
- outputs.push((constraint, out));
+ // Expands a read+write operand into two operands.
+ //
+ // Use '+' modifier when you want the same expression
+ // to be both an input and an output at the same time.
+ // It's the opposite of '=&' which means that the memory
+ // cannot be shared with any other operand (usually when
+ // a register is clobbered early.)
+ let output = match constraint.get().slice_shift_char() {
+ (Some('='), _) => None,
+ (Some('+'), operand) => {
+ // Save a reference to the output
+ read_write_operands.push((outputs.len(), out));
+ Some(token::intern_and_get_ident("=" + operand))
+ }
+ _ => {
+ cx.span_err(span, "output operand constraint lacks '=' or '+'");
+ None
+ }
+ };
+
+ outputs.push((output.unwrap_or(constraint), out));
}
}
Inputs => {
let (s, _str_style) = p.parse_str();
let clob = format!("~\\{{}\\}", s);
clobs.push(clob);
+
+ if OPTIONS.iter().any(|opt| s.equiv(opt)) {
+ cx.span_warn(p.last_span, "expected a clobber, but found an option");
+ }
}
cons = clobs.connect(",");
let (option, _str_style) = p.parse_str();
if option.equiv(&("volatile")) {
+ // Indicates that the inline assembly has side effects
+ // and must not be optimized out along with its outputs.
volatile = true;
} else if option.equiv(&("alignstack")) {
alignstack = true;
} else if option.equiv(&("intel")) {
dialect = ast::AsmIntel;
+ } else {
+ cx.span_warn(p.last_span, "unrecognized option");
}
if p.token == token::COMMA {
p.eat(&token::COMMA);
}
}
+ StateNone => ()
}
- while p.token == token::COLON ||
- p.token == token::MOD_SEP ||
- p.token == token::EOF {
- state = if p.token == token::COLON {
- p.bump();
- match next_state(state) {
- Some(x) => x,
- None => {
- continue_ = false;
- break
- }
+ loop {
+ // MOD_SEP is a double colon '::' without space in between.
+ // When encountered, the state must be advanced twice.
+ match (&p.token, state.next(), state.next().next()) {
+ (&token::COLON, StateNone, _) |
+ (&token::MOD_SEP, _, StateNone) => {
+ p.bump();
+ break 'statement;
}
- } else if p.token == token::MOD_SEP {
- p.bump();
- let s = match next_state(state) {
- Some(x) => x,
- None => {
- continue_ = false;
- break
- }
- };
- match next_state(s) {
- Some(x) => x,
- None => {
- continue_ = false;
- break
- }
+ (&token::COLON, st, _) |
+ (&token::MOD_SEP, _, st) => {
+ p.bump();
+ state = st;
}
- } else if p.token == token::EOF {
- continue_ = false;
- break;
- } else {
- state
- };
+ (&token::EOF, _, _) => break 'statement,
+ _ => break
+ }
}
}
+ // Append an input operand, with the form of ("0", expr)
+ // that links to an output operand.
+ for &(i, out) in read_write_operands.iter() {
+ inputs.push((token::intern_and_get_ident(i.to_str()), out));
+ }
+
MRExpr(@ast::Expr {
id: ast::DUMMY_NODE_ID,
node: ast::ExprInlineAsm(ast::InlineAsm {
pub fn raw_dummy_expr(sp: codemap::Span) -> @ast::Expr {
@ast::Expr {
id: ast::DUMMY_NODE_ID,
- node: ast::ExprLogLevel,
+ node: ast::ExprTup(Vec::new()),
span: sp
}
}
pub fn backtrace(&self) -> Option<@ExpnInfo> { self.backtrace }
pub fn mod_push(&mut self, i: ast::Ident) { self.mod_path.push(i); }
pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); }
- pub fn mod_path(&self) -> Vec<ast::Ident> { self.mod_path.clone() }
+ pub fn mod_path(&self) -> Vec<ast::Ident> {
+ let mut v = Vec::new();
+ v.push(token::str_to_ident(self.ecfg.crate_id.name));
+ v.extend(&mut self.mod_path.iter().map(|a| *a));
+ return v;
+ }
pub fn bt_push(&mut self, ei: codemap::ExpnInfo) {
match ei {
ExpnInfo {call_site: cs, callee: ref callee} => {
use codemap::Span;
use opt_vec;
use parse::token::InternedString;
-use parse::token;
use std::vec_ng::Vec;
use std::vec_ng;
cx.path_all(self.span, false, vec!( type_ident ), self_lifetimes,
opt_vec::take_vec(self_ty_params)), None);
- let doc_attr = cx.attribute(
+ let attr = cx.attribute(
self.span,
- cx.meta_name_value(self.span,
- InternedString::new("doc"),
- ast::LitStr(token::intern_and_get_ident(
- "Automatically derived."),
- ast::CookedStr)));
+ cx.meta_word(self.span,
+ InternedString::new("automatically_derived")));
let opt_trait_ref = Some(trait_ref);
let ident = ast_util::impl_pretty_name(&opt_trait_ref, self_type);
cx.item(
self.span,
ident,
- vec_ng::append(vec!(doc_attr), self.attributes.as_slice()),
+ vec_ng::append(vec!(attr), self.attributes.as_slice()),
ast::ItemImpl(trait_generics, opt_trait_ref,
self_type, methods.map(|x| *x)))
}
use attr::AttrMetaMethods;
use codemap;
use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute};
+use crateid::CrateId;
use ext::base::*;
use fold::*;
use parse;
pub struct ExpansionConfig<'a> {
loader: &'a mut CrateLoader,
deriving_hash_type_parameter: bool,
+ crate_id: CrateId,
}
pub fn expand_crate(parse_sess: @parse::ParseSess,
let cfg = ::syntax::ext::expand::ExpansionConfig {
loader: &mut loader,
deriving_hash_type_parameter: false,
+ crate_id: from_str("test").unwrap(),
};
expand_crate(sess,cfg,crate_ast);
}
let cfg = ::syntax::ext::expand::ExpansionConfig {
loader: &mut loader,
deriving_hash_type_parameter: false,
+ crate_id: from_str("test").unwrap(),
};
expand_crate(sess,cfg,crate_ast);
}
let cfg = ::syntax::ext::expand::ExpansionConfig {
loader: &mut loader,
deriving_hash_type_parameter: false,
+ crate_id: from_str("test").unwrap(),
};
expand_crate(sess, cfg, crate_ast);
}
let cfg = ::syntax::ext::expand::ExpansionConfig {
loader: &mut loader,
deriving_hash_type_parameter: false,
+ crate_id: from_str("test").unwrap(),
};
expand_crate(ps,cfg,crate_ast)
}
ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
}
ExprPath(ref pth) => ExprPath(folder.fold_path(pth)),
- ExprLogLevel => ExprLogLevel,
ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
ExprRet(ref e) => {
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://static.rust-lang.org/doc/master")];
-#[feature(macro_rules, globs, managed_boxes, default_type_params)];
-#[allow(unknown_features)];// Note: remove it after a snapshot.
-#[feature(quote)];
+#[feature(macro_rules, globs, managed_boxes, default_type_params, phase, quote)];
#[allow(deprecated)];
#[deny(non_camel_case_types)];
+#[allow(deprecated_owned_vector)];
extern crate serialize;
extern crate term;
extern crate collections;
+#[phase(syntax, link)]
+extern crate log;
pub mod util {
pub mod interner;
use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
use ast::{ExprBreak, ExprCall, ExprCast};
use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex};
-use ast::{ExprLit, ExprLogLevel, ExprLoop, ExprMac};
+use ast::{ExprLit, ExprLoop, ExprMac};
use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc};
use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
use ast::{ExprVec, ExprVstore, ExprVstoreSlice};
bounds
} = self.parse_path(LifetimeAndTypesAndBounds);
TyPath(path, bounds, ast::DUMMY_NODE_ID)
+ } else if self.eat(&token::UNDERSCORE) {
+ // TYPE TO BE INFERRED
+ TyInfer
} else {
let msg = format!("expected type, found token {:?}", self.token);
self.fatal(msg);
}
}
hi = self.last_span.hi;
- } else if self.eat_keyword(keywords::__LogLevel) {
- // LOG LEVEL expression
- self.expect(&token::LPAREN);
- ex = ExprLogLevel;
- hi = self.span.hi;
- self.expect(&token::RPAREN);
} else if self.eat_keyword(keywords::Return) {
// RETURN expression
if can_begin_expr(&self.token) {
///
/// # Example
///
- /// extern crate extra;
+ /// extern crate url;
/// extern crate foo = "bar";
fn parse_item_extern_crate(&mut self,
lo: BytePos,
(20, Impl, "impl");
(21, In, "in");
(22, Let, "let");
- (23, __LogLevel, "__log_level");
- (24, Loop, "loop");
- (25, Match, "match");
- (26, Mod, "mod");
- (27, Mut, "mut");
- (28, Once, "once");
- (29, Priv, "priv");
- (30, Pub, "pub");
- (31, Ref, "ref");
- (32, Return, "return");
+ (23, Loop, "loop");
+ (24, Match, "match");
+ (25, Mod, "mod");
+ (26, Mut, "mut");
+ (27, Once, "once");
+ (28, Priv, "priv");
+ (29, Pub, "pub");
+ (30, Ref, "ref");
+ (31, Return, "return");
// Static and Self are also special idents (prefill de-dupes)
(super::STATIC_KEYWORD_NAME, Static, "static");
(super::SELF_KEYWORD_NAME, Self, "self");
- (33, Struct, "struct");
- (34, Super, "super");
- (35, True, "true");
- (36, Trait, "trait");
- (37, Type, "type");
- (38, Unsafe, "unsafe");
- (39, Use, "use");
- (40, While, "while");
- (41, Continue, "continue");
- (42, Proc, "proc");
- (43, Box, "box");
+ (32, Struct, "struct");
+ (33, Super, "super");
+ (34, True, "true");
+ (35, Trait, "trait");
+ (36, Type, "type");
+ (37, Unsafe, "unsafe");
+ (38, Use, "use");
+ (39, While, "while");
+ (40, Continue, "continue");
+ (41, Proc, "proc");
+ (42, Box, "box");
'reserved:
- (44, Alignof, "alignof");
- (45, Be, "be");
- (46, Offsetof, "offsetof");
- (47, Pure, "pure");
- (48, Sizeof, "sizeof");
- (49, Typeof, "typeof");
- (50, Unsized, "unsized");
- (51, Yield, "yield");
- (52, Do, "do");
+ (43, Alignof, "alignof");
+ (44, Be, "be");
+ (45, Offsetof, "offsetof");
+ (46, Pure, "pure");
+ (47, Sizeof, "sizeof");
+ (48, Typeof, "typeof");
+ (49, Unsized, "unsized");
+ (50, Yield, "yield");
+ (51, Do, "do");
}
}
try!(word(&mut s.s, ")"));
}
ast::TyInfer => {
- fail!("print_type shouldn't see a ty_infer");
+ try!(word(&mut s.s, "_"));
}
}
end(s)
_ => ()
}
}
- ast::ExprLogLevel => {
- try!(word(&mut s.s, "__log_level"));
- try!(popen(s));
- try!(pclose(s));
- }
ast::ExprInlineAsm(ref a) => {
if a.volatile {
try!(word(&mut s.s, "__volatile__ asm!"));
ExprRet(optional_expression) => {
walk_expr_opt(visitor, optional_expression, env.clone())
}
- ExprLogLevel => {}
ExprMac(ref macro) => visitor.visit_mac(macro, env.clone()),
ExprParen(subexpression) => {
visitor.visit_expr(subexpression, env.clone())
#[feature(macro_rules)];
#[deny(non_camel_case_types)];
#[allow(missing_doc)];
+#[allow(deprecated_owned_vector)];
extern crate collections;
if s.is_ok() {
try!(self.out.write(s.unwrap()));
return Ok(true)
- } else {
- warn!("{}", s.unwrap_err());
}
}
Ok(false)
if s.is_ok() {
try!(self.out.write(s.unwrap()));
return Ok(true)
- } else {
- warn!("{}", s.unwrap_err());
}
}
Ok(false)
if s.is_ok() {
try!(self.out.write(s.unwrap()));
return Ok(true)
- } else {
- warn!("{}", s.unwrap_err());
}
}
Ok(false)
});
if s.is_ok() {
return self.out.write(s.unwrap())
- } else if self.num_colors > 0 {
- warn!("{}", s.unwrap_err());
- } else {
- // if we support attributes but not color, it would be nice to still warn!()
- // but it's not worth testing all known attributes just for this.
- debug!("{}", s.unwrap_err());
}
Ok(())
}
assert!(names_bytes > 0);
- debug!("names_bytes = {}", names_bytes);
- debug!("bools_bytes = {}", bools_bytes);
- debug!("numbers_count = {}", numbers_count);
- debug!("string_offsets_count = {}", string_offsets_count);
- debug!("string_table_bytes = {}", string_table_bytes);
-
if (bools_bytes as uint) > boolnames.len() {
- error!("expected bools_bytes to be less than {} but found {}", boolnames.len(),
- bools_bytes);
return Err(~"incompatible file: more booleans than expected");
}
if (numbers_count as uint) > numnames.len() {
- error!("expected numbers_count to be less than {} but found {}", numnames.len(),
- numbers_count);
return Err(~"incompatible file: more numbers than expected");
}
if (string_offsets_count as uint) > stringnames.len() {
- error!("expected string_offsets_count to be less than {} but found {}", stringnames.len(),
- string_offsets_count);
return Err(~"incompatible file: more string offsets than expected");
}
try!(file.read_byte()); // consume NUL
- debug!("term names: {:?}", term_names);
-
let mut bools_map = HashMap::new();
if bools_bytes != 0 {
for i in range(0, bools_bytes) {
let b = try!(file.read_byte());
if b < 0 {
- error!("EOF reading bools after {} entries", i);
return Err(~"error: expected more bools but hit EOF");
} else if b == 1 {
- debug!("{} set", bnames[i]);
bools_map.insert(bnames[i].to_owned(), true);
}
}
}
- debug!("bools: {:?}", bools_map);
-
if (bools_bytes + names_bytes) % 2 == 1 {
- debug!("adjusting for padding between bools and numbers");
try!(file.read_byte()); // compensate for padding
}
for i in range(0, numbers_count) {
let n = try!(file.read_le_u16());
if n != 0xFFFF {
- debug!("{}\\#{}", nnames[i], n);
numbers_map.insert(nnames[i].to_owned(), n);
}
}
}
- debug!("numbers: {:?}", numbers_map);
-
let mut string_map = HashMap::new();
if string_offsets_count != 0 {
string_offsets.push(try!(file.read_le_u16()));
}
- debug!("offsets: {:?}", string_offsets);
-
let string_table = try!(file.read_bytes(string_table_bytes as uint));
if string_table.len() != string_table_bytes as uint {
- error!("EOF reading string table after {} bytes, wanted {}", string_table.len(),
- string_table_bytes);
return Err(~"error: hit EOF before end of string table");
}
#[license = "MIT/ASL2"];
#[crate_type = "rlib"];
#[crate_type = "dylib"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
-#[feature(asm)];
+#[feature(asm, macro_rules)];
+#[allow(deprecated_owned_vector)];
extern crate collections;
-extern crate extra;
extern crate getopts;
extern crate serialize;
extern crate term;
extern crate time;
use collections::TreeMap;
-use extra::stats::Stats;
-use extra::stats;
+use stats::Stats;
use time::precise_time_ns;
use getopts::{OptGroup, optflag, optopt};
use serialize::{json, Decodable};
MetricChange, Improvement, Regression, LikelyNoise,
StaticTestFn, StaticTestName, DynTestName, DynTestFn,
run_test, test_main, test_main_static, filter_tests,
- parse_opts};
+ parse_opts, StaticBenchFn};
}
+pub mod stats;
+
// The name of a test. By convention this follows the rules for rust
// paths; i.e. it should be a series of identifiers separated by double
// colons. This way if some test runner wants to arrange the tests
tests: ~[TestDescAndFn]) -> io::IoResult<bool> {
fn callback<T: Writer>(event: &TestEvent,
st: &mut ConsoleTestState<T>) -> io::IoResult<()> {
- debug!("callback(event={:?})", event);
match (*event).clone() {
TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()),
TeWait(ref test, padding) => st.write_test_start(test, padding),
match tests.iter().max_by(|t|len_if_padded(*t)) {
Some(t) => {
let n = t.desc.name.to_str();
- debug!("Setting max_name_len from: {}", n);
st.max_name_len = n.len();
},
None => {}
// It's tempting to just spawn all the tests at once, but since we have
// many tests that run in other processes we would be making a big mess.
let concurrency = get_concurrency();
- debug!("using {} test tasks", concurrency);
let mut remaining = filtered_tests;
remaining.reverse();
if delta.abs() <= noise {
LikelyNoise
} else {
- let pct = delta.abs() / cmp::max(vold.value, f64::EPSILON) * 100.0;
+ let pct = delta.abs() / vold.value.max(f64::EPSILON) * 100.0;
if vold.noise < 0.0 {
// When 'noise' is negative, it means we want
// to see deltas that go up over time, and can
});
if ok {
- debug!("rewriting file '{:?}' with updated metrics", p);
self.save(p).unwrap();
}
return (diff, ok)
pub fn bench_n(&mut self, n: u64, f: |&mut BenchHarness|) {
self.iterations = n;
- debug!("running benchmark for {} iterations",
- n as uint);
f(self);
}
// (i.e. larger error bars).
if n == 0 { n = 1; }
- debug!("Initial run took {} ns, iter count that takes 1ms estimated as {}",
- self.ns_per_iter(), n);
-
let mut total_run = 0;
let samples : &mut [f64] = [0.0_f64, ..50];
loop {
stats::winsorize(samples, 5.0);
let summ5 = stats::Summary::new(samples);
- debug!("{} samples, median {}, MAD={}, MADP={}",
- samples.len(),
- summ.median as f64,
- summ.median_abs_dev as f64,
- summ.median_abs_dev_pct as f64);
-
let now = precise_time_ns();
let loop_run = now - loop_start;
Metric, MetricMap, MetricAdded, MetricRemoved,
Improvement, Regression, LikelyNoise,
StaticTestName, DynTestName, DynTestFn};
- use extra::tempfile::TempDir;
+ use std::io::TempDir;
#[test]
pub fn do_not_run_ignored_tests() {
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[allow(missing_doc)];
+
+use std::hash::Hash;
+use std::io;
+use std::mem;
+use std::num;
+use collections::hashmap;
+
+// NB: this can probably be rewritten in terms of num::Num
+// to be less f64-specific.
+
+fn f64_cmp(x: f64, y: f64) -> Ordering {
+ // arbitrarily decide that NaNs are larger than everything.
+ if y.is_nan() {
+ Less
+ } else if x.is_nan() {
+ Greater
+ } else if x < y {
+ Less
+ } else if x == y {
+ Equal
+ } else {
+ Greater
+ }
+}
+
+fn f64_sort(v: &mut [f64]) {
+ v.sort_by(|x: &f64, y: &f64| f64_cmp(*x, *y));
+}
+
+/// Trait that provides simple descriptive statistics on a univariate set of numeric samples.
+pub trait Stats {
+
+ /// Sum of the samples.
+ ///
+ /// Note: this method sacrifices performance at the altar of accuracy
+ /// Depends on IEEE-754 arithmetic guarantees. See proof of correctness at:
+ /// ["Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates"]
+ /// (http://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps)
+ /// *Discrete & Computational Geometry 18*, 3 (Oct 1997), 305-363, Shewchuk J.R.
+ fn sum(self) -> f64;
+
+ /// Minimum value of the samples.
+ fn min(self) -> f64;
+
+ /// Maximum value of the samples.
+ fn max(self) -> f64;
+
+ /// Arithmetic mean (average) of the samples: sum divided by sample-count.
+ ///
+ /// See: https://en.wikipedia.org/wiki/Arithmetic_mean
+ fn mean(self) -> f64;
+
+ /// Median of the samples: value separating the lower half of the samples from the higher half.
+ /// Equal to `self.percentile(50.0)`.
+ ///
+ /// See: https://en.wikipedia.org/wiki/Median
+ fn median(self) -> f64;
+
+ /// Variance of the samples: bias-corrected mean of the squares of the differences of each
+ /// sample from the sample mean. Note that this calculates the _sample variance_ rather than the
+ /// population variance, which is assumed to be unknown. It therefore corrects the `(n-1)/n`
+ /// bias that would appear if we calculated a population variance, by dividing by `(n-1)` rather
+ /// than `n`.
+ ///
+ /// See: https://en.wikipedia.org/wiki/Variance
+ fn var(self) -> f64;
+
+ /// Standard deviation: the square root of the sample variance.
+ ///
+ /// Note: this is not a robust statistic for non-normal distributions. Prefer the
+ /// `median_abs_dev` for unknown distributions.
+ ///
+ /// See: https://en.wikipedia.org/wiki/Standard_deviation
+ fn std_dev(self) -> f64;
+
+ /// Standard deviation as a percent of the mean value. See `std_dev` and `mean`.
+ ///
+ /// Note: this is not a robust statistic for non-normal distributions. Prefer the
+ /// `median_abs_dev_pct` for unknown distributions.
+ fn std_dev_pct(self) -> f64;
+
+ /// Scaled median of the absolute deviations of each sample from the sample median. This is a
+ /// robust (distribution-agnostic) estimator of sample variability. Use this in preference to
+ /// `std_dev` if you cannot assume your sample is normally distributed. Note that this is scaled
+ /// by the constant `1.4826` to allow its use as a consistent estimator for the standard
+ /// deviation.
+ ///
+ /// See: http://en.wikipedia.org/wiki/Median_absolute_deviation
+ fn median_abs_dev(self) -> f64;
+
+ /// Median absolute deviation as a percent of the median. See `median_abs_dev` and `median`.
+ fn median_abs_dev_pct(self) -> f64;
+
+ /// Percentile: the value below which `pct` percent of the values in `self` fall. For example,
+ /// percentile(95.0) will return the value `v` such that 95% of the samples `s` in `self`
+ /// satisfy `s <= v`.
+ ///
+ /// Calculated by linear interpolation between closest ranks.
+ ///
+ /// See: http://en.wikipedia.org/wiki/Percentile
+ fn percentile(self, pct: f64) -> f64;
+
+ /// Quartiles of the sample: three values that divide the sample into four equal groups, each
+ /// with 1/4 of the data. The middle value is the median. See `median` and `percentile`. This
+ /// function may calculate the 3 quartiles more efficiently than 3 calls to `percentile`, but
+ /// is otherwise equivalent.
+ ///
+ /// See also: https://en.wikipedia.org/wiki/Quartile
+ fn quartiles(self) -> (f64,f64,f64);
+
+ /// Inter-quartile range: the difference between the 25th percentile (1st quartile) and the 75th
+ /// percentile (3rd quartile). See `quartiles`.
+ ///
+ /// See also: https://en.wikipedia.org/wiki/Interquartile_range
+ fn iqr(self) -> f64;
+}
+
+/// Extracted collection of all the summary statistics of a sample set.
+#[deriving(Clone, Eq)]
+#[allow(missing_doc)]
+pub struct Summary {
+ sum: f64,
+ min: f64,
+ max: f64,
+ mean: f64,
+ median: f64,
+ var: f64,
+ std_dev: f64,
+ std_dev_pct: f64,
+ median_abs_dev: f64,
+ median_abs_dev_pct: f64,
+ quartiles: (f64,f64,f64),
+ iqr: f64,
+}
+
+impl Summary {
+
+ /// Construct a new summary of a sample set.
+ pub fn new(samples: &[f64]) -> Summary {
+ Summary {
+ sum: samples.sum(),
+ min: samples.min(),
+ max: samples.max(),
+ mean: samples.mean(),
+ median: samples.median(),
+ var: samples.var(),
+ std_dev: samples.std_dev(),
+ std_dev_pct: samples.std_dev_pct(),
+ median_abs_dev: samples.median_abs_dev(),
+ median_abs_dev_pct: samples.median_abs_dev_pct(),
+ quartiles: samples.quartiles(),
+ iqr: samples.iqr()
+ }
+ }
+}
+
+impl<'a> Stats for &'a [f64] {
+
+ // FIXME #11059 handle NaN, inf and overflow
+ fn sum(self) -> f64 {
+ let mut partials : ~[f64] = ~[];
+
+ for &mut x in self.iter() {
+ let mut j = 0;
+ // This inner loop applies `hi`/`lo` summation to each
+ // partial so that the list of partial sums remains exact.
+ for i in range(0, partials.len()) {
+ let mut y = partials[i];
+ if num::abs(x) < num::abs(y) {
+ mem::swap(&mut x, &mut y);
+ }
+ // Rounded `x+y` is stored in `hi` with round-off stored in
+ // `lo`. Together `hi+lo` are exactly equal to `x+y`.
+ let hi = x + y;
+ let lo = y - (hi - x);
+ if lo != 0f64 {
+ partials[j] = lo;
+ j += 1;
+ }
+ x = hi;
+ }
+ if j >= partials.len() {
+ partials.push(x);
+ } else {
+ partials[j] = x;
+ partials.truncate(j+1);
+ }
+ }
+ partials.iter().fold(0.0, |p, q| p + *q)
+ }
+
+ fn min(self) -> f64 {
+ assert!(self.len() != 0);
+ self.iter().fold(self[0], |p, q| p.min(*q))
+ }
+
+ fn max(self) -> f64 {
+ assert!(self.len() != 0);
+ self.iter().fold(self[0], |p, q| p.max(*q))
+ }
+
+ fn mean(self) -> f64 {
+ assert!(self.len() != 0);
+ self.sum() / (self.len() as f64)
+ }
+
+ fn median(self) -> f64 {
+ self.percentile(50.0)
+ }
+
+ fn var(self) -> f64 {
+ if self.len() < 2 {
+ 0.0
+ } else {
+ let mean = self.mean();
+ let mut v = 0.0;
+ for s in self.iter() {
+ let x = *s - mean;
+ v += x*x;
+ }
+ // NB: this is _supposed to be_ len-1, not len. If you
+ // change it back to len, you will be calculating a
+ // population variance, not a sample variance.
+ v/((self.len()-1) as f64)
+ }
+ }
+
+ fn std_dev(self) -> f64 {
+ self.var().sqrt()
+ }
+
+ fn std_dev_pct(self) -> f64 {
+ (self.std_dev() / self.mean()) * 100.0
+ }
+
+ fn median_abs_dev(self) -> f64 {
+ let med = self.median();
+ let abs_devs = self.map(|&v| num::abs(med - v));
+ // This constant is derived by smarter statistics brains than me, but it is
+ // consistent with how R and other packages treat the MAD.
+ abs_devs.median() * 1.4826
+ }
+
+ fn median_abs_dev_pct(self) -> f64 {
+ (self.median_abs_dev() / self.median()) * 100.0
+ }
+
+ fn percentile(self, pct: f64) -> f64 {
+ let mut tmp = self.to_owned();
+ f64_sort(tmp);
+ percentile_of_sorted(tmp, pct)
+ }
+
+ fn quartiles(self) -> (f64,f64,f64) {
+ let mut tmp = self.to_owned();
+ f64_sort(tmp);
+ let a = percentile_of_sorted(tmp, 25.0);
+ let b = percentile_of_sorted(tmp, 50.0);
+ let c = percentile_of_sorted(tmp, 75.0);
+ (a,b,c)
+ }
+
+ fn iqr(self) -> f64 {
+ let (a,_,c) = self.quartiles();
+ c - a
+ }
+}
+
+
+// Helper function: extract a value representing the `pct` percentile of a sorted sample-set, using
+// linear interpolation. If samples are not sorted, return nonsensical value.
+fn percentile_of_sorted(sorted_samples: &[f64],
+ pct: f64) -> f64 {
+ assert!(sorted_samples.len() != 0);
+ if sorted_samples.len() == 1 {
+ return sorted_samples[0];
+ }
+ assert!(0.0 <= pct);
+ assert!(pct <= 100.0);
+ if pct == 100.0 {
+ return sorted_samples[sorted_samples.len() - 1];
+ }
+ let rank = (pct / 100.0) * ((sorted_samples.len() - 1) as f64);
+ let lrank = rank.floor();
+ let d = rank - lrank;
+ let n = lrank as uint;
+ let lo = sorted_samples[n];
+ let hi = sorted_samples[n+1];
+ lo + (hi - lo) * d
+}
+
+
+/// Winsorize a set of samples, replacing values above the `100-pct` percentile and below the `pct`
+/// percentile with those percentiles themselves. This is a way of minimizing the effect of
+/// outliers, at the cost of biasing the sample. It differs from trimming in that it does not
+/// change the number of samples, just changes the values of those that are outliers.
+///
+/// See: http://en.wikipedia.org/wiki/Winsorising
+pub fn winsorize(samples: &mut [f64], pct: f64) {
+ let mut tmp = samples.to_owned();
+ f64_sort(tmp);
+ let lo = percentile_of_sorted(tmp, pct);
+ let hi = percentile_of_sorted(tmp, 100.0-pct);
+ for samp in samples.mut_iter() {
+ if *samp > hi {
+ *samp = hi
+ } else if *samp < lo {
+ *samp = lo
+ }
+ }
+}
+
+/// Render writes the min, max and quartiles of the provided `Summary` to the provided `Writer`.
+pub fn write_5_number_summary(w: &mut io::Writer,
+ s: &Summary) -> io::IoResult<()> {
+ let (q1,q2,q3) = s.quartiles;
+ write!(w, "(min={}, q1={}, med={}, q3={}, max={})",
+ s.min,
+ q1,
+ q2,
+ q3,
+ s.max)
+}
+
+/// Render a boxplot to the provided writer. The boxplot shows the min, max and quartiles of the
+/// provided `Summary` (thus includes the mean) and is scaled to display within the range of the
+/// nearest multiple-of-a-power-of-ten above and below the min and max of possible values, and
+/// target `width_hint` characters of display (though it will be wider if necessary).
+///
+/// As an example, the summary with 5-number-summary `(min=15, q1=17, med=20, q3=24, max=31)` might
+/// display as:
+///
+/// ~~~~ignore
+/// 10 | [--****#******----------] | 40
+/// ~~~~
+
+pub fn write_boxplot(w: &mut io::Writer, s: &Summary,
+ width_hint: uint) -> io::IoResult<()> {
+
+ let (q1,q2,q3) = s.quartiles;
+
+ // the .abs() handles the case where numbers are negative
+ let lomag = (10.0_f64).powf(&(s.min.abs().log10().floor()));
+ let himag = (10.0_f64).powf(&(s.max.abs().log10().floor()));
+
+ // need to consider when the limit is zero
+ let lo = if lomag == 0.0 {
+ 0.0
+ } else {
+ (s.min / lomag).floor() * lomag
+ };
+
+ let hi = if himag == 0.0 {
+ 0.0
+ } else {
+ (s.max / himag).ceil() * himag
+ };
+
+ let range = hi - lo;
+
+ let lostr = lo.to_str();
+ let histr = hi.to_str();
+
+ let overhead_width = lostr.len() + histr.len() + 4;
+ let range_width = width_hint - overhead_width;;
+ let char_step = range / (range_width as f64);
+
+ try!(write!(w, "{} |", lostr));
+
+ let mut c = 0;
+ let mut v = lo;
+
+ while c < range_width && v < s.min {
+ try!(write!(w, " "));
+ v += char_step;
+ c += 1;
+ }
+ try!(write!(w, "["));
+ c += 1;
+ while c < range_width && v < q1 {
+ try!(write!(w, "-"));
+ v += char_step;
+ c += 1;
+ }
+ while c < range_width && v < q2 {
+ try!(write!(w, "*"));
+ v += char_step;
+ c += 1;
+ }
+ try!(write!(w, r"\#"));
+ c += 1;
+ while c < range_width && v < q3 {
+ try!(write!(w, "*"));
+ v += char_step;
+ c += 1;
+ }
+ while c < range_width && v < s.max {
+ try!(write!(w, "-"));
+ v += char_step;
+ c += 1;
+ }
+ try!(write!(w, "]"));
+ while c < range_width {
+ try!(write!(w, " "));
+ v += char_step;
+ c += 1;
+ }
+
+ try!(write!(w, "| {}", histr));
+ Ok(())
+}
+
+/// Returns a HashMap with the number of occurrences of every element in the
+/// sequence that the iterator exposes.
+pub fn freq_count<T: Iterator<U>, U: Eq+Hash>(mut iter: T) -> hashmap::HashMap<U, uint> {
+ let mut map: hashmap::HashMap<U,uint> = hashmap::HashMap::new();
+ for elem in iter {
+ map.insert_or_update_with(elem, 1, |_, count| *count += 1);
+ }
+ map
+}
+
+// Test vectors generated from R, using the script src/etc/stat-test-vectors.r.
+
+#[cfg(test)]
+mod tests {
+ use stats::Stats;
+ use stats::Summary;
+ use stats::write_5_number_summary;
+ use stats::write_boxplot;
+ use std::io;
+ use std::str;
+ use std::f64;
+
+ macro_rules! assert_approx_eq(
+ ($a:expr, $b:expr) => ({
+ let (a, b) = (&$a, &$b);
+ assert!((*a - *b).abs() < 1.0e-6,
+ "{} is not approximately equal to {}", *a, *b);
+ })
+ )
+
+ fn check(samples: &[f64], summ: &Summary) {
+
+ let summ2 = Summary::new(samples);
+
+ let mut w = io::stdout();
+ let w = &mut w as &mut io::Writer;
+ (write!(w, "\n")).unwrap();
+ write_5_number_summary(w, &summ2).unwrap();
+ (write!(w, "\n")).unwrap();
+ write_boxplot(w, &summ2, 50).unwrap();
+ (write!(w, "\n")).unwrap();
+
+ assert_eq!(summ.sum, summ2.sum);
+ assert_eq!(summ.min, summ2.min);
+ assert_eq!(summ.max, summ2.max);
+ assert_eq!(summ.mean, summ2.mean);
+ assert_eq!(summ.median, summ2.median);
+
+ // We needed a few more digits to get exact equality on these
+ // but they're within float epsilon, which is 1.0e-6.
+ assert_approx_eq!(summ.var, summ2.var);
+ assert_approx_eq!(summ.std_dev, summ2.std_dev);
+ assert_approx_eq!(summ.std_dev_pct, summ2.std_dev_pct);
+ assert_approx_eq!(summ.median_abs_dev, summ2.median_abs_dev);
+ assert_approx_eq!(summ.median_abs_dev_pct, summ2.median_abs_dev_pct);
+
+ assert_eq!(summ.quartiles, summ2.quartiles);
+ assert_eq!(summ.iqr, summ2.iqr);
+ }
+
+ #[test]
+ fn test_min_max_nan() {
+ let xs = &[1.0, 2.0, f64::NAN, 3.0, 4.0];
+ let summary = Summary::new(xs);
+ assert_eq!(summary.min, 1.0);
+ assert_eq!(summary.max, 4.0);
+ }
+
+ #[test]
+ fn test_norm2() {
+ let val = &[
+ 958.0000000000,
+ 924.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 1882.0000000000,
+ min: 924.0000000000,
+ max: 958.0000000000,
+ mean: 941.0000000000,
+ median: 941.0000000000,
+ var: 578.0000000000,
+ std_dev: 24.0416305603,
+ std_dev_pct: 2.5549022912,
+ median_abs_dev: 25.2042000000,
+ median_abs_dev_pct: 2.6784484591,
+ quartiles: (932.5000000000,941.0000000000,949.5000000000),
+ iqr: 17.0000000000,
+ };
+ check(val, summ);
+ }
+ #[test]
+ fn test_norm10narrow() {
+ let val = &[
+ 966.0000000000,
+ 985.0000000000,
+ 1110.0000000000,
+ 848.0000000000,
+ 821.0000000000,
+ 975.0000000000,
+ 962.0000000000,
+ 1157.0000000000,
+ 1217.0000000000,
+ 955.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 9996.0000000000,
+ min: 821.0000000000,
+ max: 1217.0000000000,
+ mean: 999.6000000000,
+ median: 970.5000000000,
+ var: 16050.7111111111,
+ std_dev: 126.6914010938,
+ std_dev_pct: 12.6742097933,
+ median_abs_dev: 102.2994000000,
+ median_abs_dev_pct: 10.5408964451,
+ quartiles: (956.7500000000,970.5000000000,1078.7500000000),
+ iqr: 122.0000000000,
+ };
+ check(val, summ);
+ }
+ #[test]
+ fn test_norm10medium() {
+ let val = &[
+ 954.0000000000,
+ 1064.0000000000,
+ 855.0000000000,
+ 1000.0000000000,
+ 743.0000000000,
+ 1084.0000000000,
+ 704.0000000000,
+ 1023.0000000000,
+ 357.0000000000,
+ 869.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 8653.0000000000,
+ min: 357.0000000000,
+ max: 1084.0000000000,
+ mean: 865.3000000000,
+ median: 911.5000000000,
+ var: 48628.4555555556,
+ std_dev: 220.5186059170,
+ std_dev_pct: 25.4846418487,
+ median_abs_dev: 195.7032000000,
+ median_abs_dev_pct: 21.4704552935,
+ quartiles: (771.0000000000,911.5000000000,1017.2500000000),
+ iqr: 246.2500000000,
+ };
+ check(val, summ);
+ }
+ #[test]
+ fn test_norm10wide() {
+ let val = &[
+ 505.0000000000,
+ 497.0000000000,
+ 1591.0000000000,
+ 887.0000000000,
+ 1026.0000000000,
+ 136.0000000000,
+ 1580.0000000000,
+ 940.0000000000,
+ 754.0000000000,
+ 1433.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 9349.0000000000,
+ min: 136.0000000000,
+ max: 1591.0000000000,
+ mean: 934.9000000000,
+ median: 913.5000000000,
+ var: 239208.9888888889,
+ std_dev: 489.0899599142,
+ std_dev_pct: 52.3146817750,
+ median_abs_dev: 611.5725000000,
+ median_abs_dev_pct: 66.9482758621,
+ quartiles: (567.2500000000,913.5000000000,1331.2500000000),
+ iqr: 764.0000000000,
+ };
+ check(val, summ);
+ }
+ #[test]
+ fn test_norm25verynarrow() {
+ let val = &[
+ 991.0000000000,
+ 1018.0000000000,
+ 998.0000000000,
+ 1013.0000000000,
+ 974.0000000000,
+ 1007.0000000000,
+ 1014.0000000000,
+ 999.0000000000,
+ 1011.0000000000,
+ 978.0000000000,
+ 985.0000000000,
+ 999.0000000000,
+ 983.0000000000,
+ 982.0000000000,
+ 1015.0000000000,
+ 1002.0000000000,
+ 977.0000000000,
+ 948.0000000000,
+ 1040.0000000000,
+ 974.0000000000,
+ 996.0000000000,
+ 989.0000000000,
+ 1015.0000000000,
+ 994.0000000000,
+ 1024.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 24926.0000000000,
+ min: 948.0000000000,
+ max: 1040.0000000000,
+ mean: 997.0400000000,
+ median: 998.0000000000,
+ var: 393.2066666667,
+ std_dev: 19.8294393937,
+ std_dev_pct: 1.9888308788,
+ median_abs_dev: 22.2390000000,
+ median_abs_dev_pct: 2.2283567134,
+ quartiles: (983.0000000000,998.0000000000,1013.0000000000),
+ iqr: 30.0000000000,
+ };
+ check(val, summ);
+ }
+ #[test]
+ fn test_exp10a() {
+ let val = &[
+ 23.0000000000,
+ 11.0000000000,
+ 2.0000000000,
+ 57.0000000000,
+ 4.0000000000,
+ 12.0000000000,
+ 5.0000000000,
+ 29.0000000000,
+ 3.0000000000,
+ 21.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 167.0000000000,
+ min: 2.0000000000,
+ max: 57.0000000000,
+ mean: 16.7000000000,
+ median: 11.5000000000,
+ var: 287.7888888889,
+ std_dev: 16.9643416875,
+ std_dev_pct: 101.5828843560,
+ median_abs_dev: 13.3434000000,
+ median_abs_dev_pct: 116.0295652174,
+ quartiles: (4.2500000000,11.5000000000,22.5000000000),
+ iqr: 18.2500000000,
+ };
+ check(val, summ);
+ }
+ #[test]
+ fn test_exp10b() {
+ let val = &[
+ 24.0000000000,
+ 17.0000000000,
+ 6.0000000000,
+ 38.0000000000,
+ 25.0000000000,
+ 7.0000000000,
+ 51.0000000000,
+ 2.0000000000,
+ 61.0000000000,
+ 32.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 263.0000000000,
+ min: 2.0000000000,
+ max: 61.0000000000,
+ mean: 26.3000000000,
+ median: 24.5000000000,
+ var: 383.5666666667,
+ std_dev: 19.5848580967,
+ std_dev_pct: 74.4671410520,
+ median_abs_dev: 22.9803000000,
+ median_abs_dev_pct: 93.7971428571,
+ quartiles: (9.5000000000,24.5000000000,36.5000000000),
+ iqr: 27.0000000000,
+ };
+ check(val, summ);
+ }
+ #[test]
+ fn test_exp10c() {
+ let val = &[
+ 71.0000000000,
+ 2.0000000000,
+ 32.0000000000,
+ 1.0000000000,
+ 6.0000000000,
+ 28.0000000000,
+ 13.0000000000,
+ 37.0000000000,
+ 16.0000000000,
+ 36.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 242.0000000000,
+ min: 1.0000000000,
+ max: 71.0000000000,
+ mean: 24.2000000000,
+ median: 22.0000000000,
+ var: 458.1777777778,
+ std_dev: 21.4050876611,
+ std_dev_pct: 88.4507754589,
+ median_abs_dev: 21.4977000000,
+ median_abs_dev_pct: 97.7168181818,
+ quartiles: (7.7500000000,22.0000000000,35.0000000000),
+ iqr: 27.2500000000,
+ };
+ check(val, summ);
+ }
+ #[test]
+ fn test_exp25() {
+ let val = &[
+ 3.0000000000,
+ 24.0000000000,
+ 1.0000000000,
+ 19.0000000000,
+ 7.0000000000,
+ 5.0000000000,
+ 30.0000000000,
+ 39.0000000000,
+ 31.0000000000,
+ 13.0000000000,
+ 25.0000000000,
+ 48.0000000000,
+ 1.0000000000,
+ 6.0000000000,
+ 42.0000000000,
+ 63.0000000000,
+ 2.0000000000,
+ 12.0000000000,
+ 108.0000000000,
+ 26.0000000000,
+ 1.0000000000,
+ 7.0000000000,
+ 44.0000000000,
+ 25.0000000000,
+ 11.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 593.0000000000,
+ min: 1.0000000000,
+ max: 108.0000000000,
+ mean: 23.7200000000,
+ median: 19.0000000000,
+ var: 601.0433333333,
+ std_dev: 24.5161851301,
+ std_dev_pct: 103.3565983562,
+ median_abs_dev: 19.2738000000,
+ median_abs_dev_pct: 101.4410526316,
+ quartiles: (6.0000000000,19.0000000000,31.0000000000),
+ iqr: 25.0000000000,
+ };
+ check(val, summ);
+ }
+ #[test]
+ fn test_binom25() {
+ let val = &[
+ 18.0000000000,
+ 17.0000000000,
+ 27.0000000000,
+ 15.0000000000,
+ 21.0000000000,
+ 25.0000000000,
+ 17.0000000000,
+ 24.0000000000,
+ 25.0000000000,
+ 24.0000000000,
+ 26.0000000000,
+ 26.0000000000,
+ 23.0000000000,
+ 15.0000000000,
+ 23.0000000000,
+ 17.0000000000,
+ 18.0000000000,
+ 18.0000000000,
+ 21.0000000000,
+ 16.0000000000,
+ 15.0000000000,
+ 31.0000000000,
+ 20.0000000000,
+ 17.0000000000,
+ 15.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 514.0000000000,
+ min: 15.0000000000,
+ max: 31.0000000000,
+ mean: 20.5600000000,
+ median: 20.0000000000,
+ var: 20.8400000000,
+ std_dev: 4.5650848842,
+ std_dev_pct: 22.2037202539,
+ median_abs_dev: 5.9304000000,
+ median_abs_dev_pct: 29.6520000000,
+ quartiles: (17.0000000000,20.0000000000,24.0000000000),
+ iqr: 7.0000000000,
+ };
+ check(val, summ);
+ }
+ #[test]
+ fn test_pois25lambda30() {
+ let val = &[
+ 27.0000000000,
+ 33.0000000000,
+ 34.0000000000,
+ 34.0000000000,
+ 24.0000000000,
+ 39.0000000000,
+ 28.0000000000,
+ 27.0000000000,
+ 31.0000000000,
+ 28.0000000000,
+ 38.0000000000,
+ 21.0000000000,
+ 33.0000000000,
+ 36.0000000000,
+ 29.0000000000,
+ 37.0000000000,
+ 32.0000000000,
+ 34.0000000000,
+ 31.0000000000,
+ 39.0000000000,
+ 25.0000000000,
+ 31.0000000000,
+ 32.0000000000,
+ 40.0000000000,
+ 24.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 787.0000000000,
+ min: 21.0000000000,
+ max: 40.0000000000,
+ mean: 31.4800000000,
+ median: 32.0000000000,
+ var: 26.5933333333,
+ std_dev: 5.1568724372,
+ std_dev_pct: 16.3814245145,
+ median_abs_dev: 5.9304000000,
+ median_abs_dev_pct: 18.5325000000,
+ quartiles: (28.0000000000,32.0000000000,34.0000000000),
+ iqr: 6.0000000000,
+ };
+ check(val, summ);
+ }
+ #[test]
+ fn test_pois25lambda40() {
+ let val = &[
+ 42.0000000000,
+ 50.0000000000,
+ 42.0000000000,
+ 46.0000000000,
+ 34.0000000000,
+ 45.0000000000,
+ 34.0000000000,
+ 49.0000000000,
+ 39.0000000000,
+ 28.0000000000,
+ 40.0000000000,
+ 35.0000000000,
+ 37.0000000000,
+ 39.0000000000,
+ 46.0000000000,
+ 44.0000000000,
+ 32.0000000000,
+ 45.0000000000,
+ 42.0000000000,
+ 37.0000000000,
+ 48.0000000000,
+ 42.0000000000,
+ 33.0000000000,
+ 42.0000000000,
+ 48.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 1019.0000000000,
+ min: 28.0000000000,
+ max: 50.0000000000,
+ mean: 40.7600000000,
+ median: 42.0000000000,
+ var: 34.4400000000,
+ std_dev: 5.8685603004,
+ std_dev_pct: 14.3978417577,
+ median_abs_dev: 5.9304000000,
+ median_abs_dev_pct: 14.1200000000,
+ quartiles: (37.0000000000,42.0000000000,45.0000000000),
+ iqr: 8.0000000000,
+ };
+ check(val, summ);
+ }
+ #[test]
+ fn test_pois25lambda50() {
+ let val = &[
+ 45.0000000000,
+ 43.0000000000,
+ 44.0000000000,
+ 61.0000000000,
+ 51.0000000000,
+ 53.0000000000,
+ 59.0000000000,
+ 52.0000000000,
+ 49.0000000000,
+ 51.0000000000,
+ 51.0000000000,
+ 50.0000000000,
+ 49.0000000000,
+ 56.0000000000,
+ 42.0000000000,
+ 52.0000000000,
+ 51.0000000000,
+ 43.0000000000,
+ 48.0000000000,
+ 48.0000000000,
+ 50.0000000000,
+ 42.0000000000,
+ 43.0000000000,
+ 42.0000000000,
+ 60.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 1235.0000000000,
+ min: 42.0000000000,
+ max: 61.0000000000,
+ mean: 49.4000000000,
+ median: 50.0000000000,
+ var: 31.6666666667,
+ std_dev: 5.6273143387,
+ std_dev_pct: 11.3913245723,
+ median_abs_dev: 4.4478000000,
+ median_abs_dev_pct: 8.8956000000,
+ quartiles: (44.0000000000,50.0000000000,52.0000000000),
+ iqr: 8.0000000000,
+ };
+ check(val, summ);
+ }
+ #[test]
+ fn test_unif25() {
+ let val = &[
+ 99.0000000000,
+ 55.0000000000,
+ 92.0000000000,
+ 79.0000000000,
+ 14.0000000000,
+ 2.0000000000,
+ 33.0000000000,
+ 49.0000000000,
+ 3.0000000000,
+ 32.0000000000,
+ 84.0000000000,
+ 59.0000000000,
+ 22.0000000000,
+ 86.0000000000,
+ 76.0000000000,
+ 31.0000000000,
+ 29.0000000000,
+ 11.0000000000,
+ 41.0000000000,
+ 53.0000000000,
+ 45.0000000000,
+ 44.0000000000,
+ 98.0000000000,
+ 98.0000000000,
+ 7.0000000000,
+ ];
+ let summ = &Summary {
+ sum: 1242.0000000000,
+ min: 2.0000000000,
+ max: 99.0000000000,
+ mean: 49.6800000000,
+ median: 45.0000000000,
+ var: 1015.6433333333,
+ std_dev: 31.8691595957,
+ std_dev_pct: 64.1488719719,
+ median_abs_dev: 45.9606000000,
+ median_abs_dev_pct: 102.1346666667,
+ quartiles: (29.0000000000,45.0000000000,79.0000000000),
+ iqr: 50.0000000000,
+ };
+ check(val, summ);
+ }
+
+ #[test]
+ fn test_boxplot_nonpositive() {
+ fn t(s: &Summary, expected: ~str) {
+ use std::io::MemWriter;
+ let mut m = MemWriter::new();
+ write_boxplot(&mut m as &mut io::Writer, s, 30).unwrap();
+ let out = str::from_utf8_owned(m.unwrap()).unwrap();
+ assert_eq!(out, expected);
+ }
+
+ t(&Summary::new([-2.0, -1.0]), ~"-2 |[------******#*****---]| -1");
+ t(&Summary::new([0.0, 2.0]), ~"0 |[-------*****#*******---]| 2");
+ t(&Summary::new([-2.0, 0.0]), ~"-2 |[------******#******---]| 0");
+
+ }
+ #[test]
+ fn test_sum_f64s() {
+ assert_eq!([0.5, 3.2321, 1.5678].sum(), 5.2999);
+ }
+ #[test]
+ fn test_sum_f64_between_ints_that_sum_to_0() {
+ assert_eq!([1e30, 1.2, -1e30].sum(), 1.2);
+ }
+}
+
+#[cfg(test)]
+mod bench {
+ use BenchHarness;
+ use std::vec;
+ use stats::Stats;
+
+ #[bench]
+ pub fn sum_three_items(bh: &mut BenchHarness) {
+ bh.iter(|| {
+ [1e20, 1.5, -1e20].sum();
+ })
+ }
+ #[bench]
+ pub fn sum_many_f64(bh: &mut BenchHarness) {
+ let nums = [-1e30, 1e60, 1e30, 1.0, -1e60];
+ let v = vec::from_fn(500, |i| nums[i%5]);
+
+ bh.iter(|| {
+ v.sum();
+ })
+ }
+}
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
-#[allow(missing_doc)];
+#[feature(phase)];
+#[allow(deprecated_owned_vector)];
+#[cfg(test)] #[phase(syntax, link)] extern crate log;
extern crate serialize;
use std::io::BufReader;
}
/// A record specifying a time value in seconds and nanoseconds.
-
-
-#[deriving(Clone, Eq, Encodable, Decodable, Show)]
+#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, Encodable, Decodable, Show)]
pub struct Timespec { sec: i64, nsec: i32 }
/*
* Timespec assumes that pre-epoch Timespecs have negative sec and positive
}
}
-impl Ord for Timespec {
- fn lt(&self, other: &Timespec) -> bool {
- self.sec < other.sec ||
- (self.sec == other.sec && self.nsec < other.nsec)
- }
-}
-
/**
* Returns the current time as a `timespec` containing the seconds and
* nanoseconds since 1970-01-01T00:00:00Z.
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Types/fns concerning URLs (see RFC 3986)
+
+#[crate_id = "url#0.10-pre"];
+#[crate_type = "rlib"];
+#[crate_type = "dylib"];
+#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
+#[feature(default_type_params)];
+#[allow(deprecated_owned_vector)];
+
+extern crate collections;
+
+use std::cmp::Eq;
+use std::fmt;
+use std::hash::Hash;
+use std::io::BufReader;
+use std::from_str::FromStr;
+use std::uint;
+use std::vec_ng::Vec;
+
+use collections::HashMap;
+
+/// A Uniform Resource Locator (URL). A URL is a form of URI (Uniform Resource
+/// Identifier) that includes network location information, such as hostname or
+/// port number.
+///
+/// # Example
+///
+/// ```rust
+/// use url::{Url, UserInfo};
+///
+/// let url = Url { scheme: ~"https",
+/// user: Some(UserInfo { user: ~"username", pass: None }),
+/// host: ~"example.com",
+/// port: Some(~"8080"),
+/// path: ~"/foo/bar",
+/// query: vec!((~"baz", ~"qux")),
+/// fragment: Some(~"quz") };
+/// // https://username@example.com:8080/foo/bar?baz=qux#quz
+/// ```
+#[deriving(Clone, Eq)]
+pub struct Url {
+ /// The scheme part of a URL, such as `https` in the above example.
+ scheme: ~str,
+ /// A URL subcomponent for user authentication. `username` in the above example.
+ user: Option<UserInfo>,
+ /// A domain name or IP address. For example, `example.com`.
+ host: ~str,
+ /// A TCP port number, for example `8080`.
+ port: Option<~str>,
+ /// The path component of a URL, for example `/foo/bar`.
+ path: ~str,
+ /// The query component of a URL. `vec!((~"baz", ~"qux"))` represents the
+ /// fragment `baz=qux` in the above example.
+ query: Query,
+ /// The fragment component, such as `quz`. Doesn't include the leading `#` character.
+ fragment: Option<~str>
+}
+
+#[deriving(Clone, Eq)]
+pub struct Path {
+ /// The path component of a URL, for example `/foo/bar`.
+ path: ~str,
+ /// The query component of a URL. `vec!((~"baz", ~"qux"))` represents the
+ /// fragment `baz=qux` in the above example.
+ query: Query,
+ /// The fragment component, such as `quz`. Doesn't include the leading `#` character.
+ fragment: Option<~str>
+}
+
+/// An optional subcomponent of a URI authority component.
+#[deriving(Clone, Eq)]
+pub struct UserInfo {
+ /// The user name.
+ user: ~str,
+ /// Password or other scheme-specific authentication information.
+ pass: Option<~str>
+}
+
+/// Represents the query component of a URI.
+pub type Query = Vec<(~str, ~str)>;
+
+impl Url {
+ pub fn new(scheme: ~str,
+ user: Option<UserInfo>,
+ host: ~str,
+ port: Option<~str>,
+ path: ~str,
+ query: Query,
+ fragment: Option<~str>)
+ -> Url {
+ Url {
+ scheme: scheme,
+ user: user,
+ host: host,
+ port: port,
+ path: path,
+ query: query,
+ fragment: fragment,
+ }
+ }
+}
+
+impl Path {
+ pub fn new(path: ~str,
+ query: Query,
+ fragment: Option<~str>)
+ -> Path {
+ Path {
+ path: path,
+ query: query,
+ fragment: fragment,
+ }
+ }
+}
+
+impl UserInfo {
+ #[inline]
+ pub fn new(user: ~str, pass: Option<~str>) -> UserInfo {
+ UserInfo { user: user, pass: pass }
+ }
+}
+
+fn encode_inner(s: &str, full_url: bool) -> ~str {
+ let mut rdr = BufReader::new(s.as_bytes());
+ let mut out = ~"";
+
+ loop {
+ let mut buf = [0];
+ let ch = match rdr.read(buf) {
+ Err(..) => break,
+ Ok(..) => buf[0] as char,
+ };
+
+ match ch {
+ // unreserved:
+ 'A' .. 'Z' |
+ 'a' .. 'z' |
+ '0' .. '9' |
+ '-' | '.' | '_' | '~' => {
+ out.push_char(ch);
+ }
+ _ => {
+ if full_url {
+ match ch {
+ // gen-delims:
+ ':' | '/' | '?' | '#' | '[' | ']' | '@' |
+
+ // sub-delims:
+ '!' | '$' | '&' | '"' | '(' | ')' | '*' |
+ '+' | ',' | ';' | '=' => {
+ out.push_char(ch);
+ }
+
+ _ => out.push_str(format!("%{:X}", ch as uint))
+ }
+ } else {
+ out.push_str(format!("%{:X}", ch as uint));
+ }
+ }
+ }
+ }
+
+ out
+}
+
+/**
+ * Encodes a URI by replacing reserved characters with percent-encoded
+ * character sequences.
+ *
+ * This function is compliant with RFC 3986.
+ *
+ * # Example
+ *
+ * ```rust
+ * use url::encode;
+ *
+ * let url = encode(&"https://example.com/Rust (programming language)");
+ * println!("{}", url); // https://example.com/Rust%20(programming%20language)
+ * ```
+ */
+pub fn encode(s: &str) -> ~str {
+ encode_inner(s, true)
+}
+
+/**
+ * Encodes a URI component by replacing reserved characters with percent
+ * encoded character sequences.
+ *
+ * This function is compliant with RFC 3986.
+ */
+
+pub fn encode_component(s: &str) -> ~str {
+ encode_inner(s, false)
+}
+
+fn decode_inner(s: &str, full_url: bool) -> ~str {
+ let mut rdr = BufReader::new(s.as_bytes());
+ let mut out = ~"";
+
+ loop {
+ let mut buf = [0];
+ let ch = match rdr.read(buf) {
+ Err(..) => break,
+ Ok(..) => buf[0] as char
+ };
+ match ch {
+ '%' => {
+ let mut bytes = [0, 0];
+ match rdr.read(bytes) {
+ Ok(2) => {}
+ _ => fail!() // FIXME: malformed url?
+ }
+ let ch = uint::parse_bytes(bytes, 16u).unwrap() as u8 as char;
+
+ if full_url {
+ // Only decode some characters:
+ match ch {
+ // gen-delims:
+ ':' | '/' | '?' | '#' | '[' | ']' | '@' |
+
+ // sub-delims:
+ '!' | '$' | '&' | '"' | '(' | ')' | '*' |
+ '+' | ',' | ';' | '=' => {
+ out.push_char('%');
+ out.push_char(bytes[0u] as char);
+ out.push_char(bytes[1u] as char);
+ }
+
+ ch => out.push_char(ch)
+ }
+ } else {
+ out.push_char(ch);
+ }
+ }
+ ch => out.push_char(ch)
+ }
+ }
+
+ out
+}
+
+/**
+ * Decodes a percent-encoded string representing a URI.
+ *
+ * This will only decode escape sequences generated by `encode`.
+ *
+ * # Example
+ *
+ * ```rust
+ * use url::decode;
+ *
+ * let url = decode(&"https://example.com/Rust%20(programming%20language)");
+ * println!("{}", url); // https://example.com/Rust (programming language)
+ * ```
+ */
+pub fn decode(s: &str) -> ~str {
+ decode_inner(s, true)
+}
+
+/**
+ * Decode a string encoded with percent encoding.
+ */
+pub fn decode_component(s: &str) -> ~str {
+ decode_inner(s, false)
+}
+
+fn encode_plus(s: &str) -> ~str {
+ let mut rdr = BufReader::new(s.as_bytes());
+ let mut out = ~"";
+
+ loop {
+ let mut buf = [0];
+ let ch = match rdr.read(buf) {
+ Ok(..) => buf[0] as char,
+ Err(..) => break,
+ };
+ match ch {
+ 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_' | '.' | '-' => {
+ out.push_char(ch);
+ }
+ ' ' => out.push_char('+'),
+ _ => out.push_str(format!("%{:X}", ch as uint))
+ }
+ }
+
+ out
+}
+
+/**
+ * Encode a hashmap to the 'application/x-www-form-urlencoded' media type.
+ */
+pub fn encode_form_urlencoded(m: &HashMap<~str, Vec<~str>>) -> ~str {
+ let mut out = ~"";
+ let mut first = true;
+
+ for (key, values) in m.iter() {
+ let key = encode_plus(*key);
+
+ for value in values.iter() {
+ if first {
+ first = false;
+ } else {
+ out.push_char('&');
+ first = false;
+ }
+
+ out.push_str(format!("{}={}", key, encode_plus(*value)));
+ }
+ }
+
+ out
+}
+
+/**
+ * Decode a string encoded with the 'application/x-www-form-urlencoded' media
+ * type into a hashmap.
+ */
+pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, Vec<~str>> {
+ let mut rdr = BufReader::new(s);
+ let mut m = HashMap::new();
+ let mut key = ~"";
+ let mut value = ~"";
+ let mut parsing_key = true;
+
+ loop {
+ let mut buf = [0];
+ let ch = match rdr.read(buf) {
+ Ok(..) => buf[0] as char,
+ Err(..) => break,
+ };
+ match ch {
+ '&' | ';' => {
+ if key != ~"" && value != ~"" {
+ let mut values = match m.pop(&key) {
+ Some(values) => values,
+ None => vec!(),
+ };
+
+ values.push(value);
+ m.insert(key, values);
+ }
+
+ parsing_key = true;
+ key = ~"";
+ value = ~"";
+ }
+ '=' => parsing_key = false,
+ ch => {
+ let ch = match ch {
+ '%' => {
+ let mut bytes = [0, 0];
+ match rdr.read(bytes) {
+ Ok(2) => {}
+ _ => fail!() // FIXME: malformed?
+ }
+ uint::parse_bytes(bytes, 16u).unwrap() as u8 as char
+ }
+ '+' => ' ',
+ ch => ch
+ };
+
+ if parsing_key {
+ key.push_char(ch)
+ } else {
+ value.push_char(ch)
+ }
+ }
+ }
+ }
+
+ if key != ~"" && value != ~"" {
+ let mut values = match m.pop(&key) {
+ Some(values) => values,
+ None => vec!(),
+ };
+
+ values.push(value);
+ m.insert(key, values);
+ }
+
+ m
+}
+
+
+fn split_char_first(s: &str, c: char) -> (~str, ~str) {
+ let len = s.len();
+ let mut index = len;
+ let mut mat = 0;
+ let mut rdr = BufReader::new(s.as_bytes());
+ loop {
+ let mut buf = [0];
+ let ch = match rdr.read(buf) {
+ Ok(..) => buf[0] as char,
+ Err(..) => break,
+ };
+ if ch == c {
+ // found a match, adjust markers
+ index = (rdr.tell().unwrap() as uint) - 1;
+ mat = 1;
+ break;
+ }
+ }
+ if index+mat == len {
+ return (s.slice(0, index).to_owned(), ~"");
+ } else {
+ return (s.slice(0, index).to_owned(),
+ s.slice(index + mat, s.len()).to_owned());
+ }
+}
+
+impl fmt::Show for UserInfo {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self.pass {
+ Some(ref pass) => write!(f.buf, "{}:{}@", self.user, *pass),
+ None => write!(f.buf, "{}@", self.user),
+ }
+ }
+}
+
+fn query_from_str(rawquery: &str) -> Query {
+ let mut query: Query = vec!();
+ if !rawquery.is_empty() {
+ for p in rawquery.split('&') {
+ let (k, v) = split_char_first(p, '=');
+ query.push((decode_component(k), decode_component(v)));
+ };
+ }
+ return query;
+}
+
+/**
+ * Converts an instance of a URI `Query` type to a string.
+ *
+ * # Example
+ *
+ * ```rust
+ * let query = vec!((~"title", ~"The Village"), (~"north", ~"52.91"), (~"west", ~"4.10"));
+ * println!("{}", url::query_to_str(&query)); // title=The%20Village&north=52.91&west=4.10
+ * ```
+ */
+#[allow(unused_must_use)]
+pub fn query_to_str(query: &Query) -> ~str {
+ use std::io::MemWriter;
+ use std::str;
+
+ let mut writer = MemWriter::new();
+ for (i, &(ref k, ref v)) in query.iter().enumerate() {
+ if i != 0 { write!(&mut writer, "&"); }
+ write!(&mut writer, "{}={}", encode_component(*k),
+ encode_component(*v));
+ }
+ str::from_utf8_lossy(writer.unwrap()).into_owned()
+}
+
+/**
+ * Returns a tuple of the URI scheme and the rest of the URI, or a parsing error.
+ *
+ * Does not include the separating `:` character.
+ *
+ * # Example
+ *
+ * ```rust
+ * use url::get_scheme;
+ *
+ * let scheme = match get_scheme("https://example.com/") {
+ * Ok((sch, _)) => sch,
+ * Err(_) => ~"(None)",
+ * };
+ * println!("Scheme in use: {}.", scheme); // Scheme in use: https.
+ * ```
+ */
+pub fn get_scheme(rawurl: &str) -> Result<(~str, ~str), ~str> {
+ for (i,c) in rawurl.chars().enumerate() {
+ match c {
+ 'A' .. 'Z' | 'a' .. 'z' => continue,
+ '0' .. '9' | '+' | '-' | '.' => {
+ if i == 0 {
+ return Err(~"url: Scheme must begin with a letter.");
+ }
+ continue;
+ }
+ ':' => {
+ if i == 0 {
+ return Err(~"url: Scheme cannot be empty.");
+ } else {
+ return Ok((rawurl.slice(0,i).to_owned(),
+ rawurl.slice(i+1,rawurl.len()).to_owned()));
+ }
+ }
+ _ => {
+ return Err(~"url: Invalid character in scheme.");
+ }
+ }
+ };
+ return Err(~"url: Scheme must be terminated with a colon.");
+}
+
+#[deriving(Clone, Eq)]
+enum Input {
+ Digit, // all digits
+ Hex, // digits and letters a-f
+ Unreserved // all other legal characters
+}
+
+// returns userinfo, host, port, and unparsed part, or an error
+fn get_authority(rawurl: &str) ->
+ Result<(Option<UserInfo>, ~str, Option<~str>, ~str), ~str> {
+ if !rawurl.starts_with("//") {
+ // there is no authority.
+ return Ok((None, ~"", None, rawurl.to_str()));
+ }
+
+ enum State {
+ Start, // starting state
+ PassHostPort, // could be in user or port
+ Ip6Port, // either in ipv6 host or port
+ Ip6Host, // are in an ipv6 host
+ InHost, // are in a host - may be ipv6, but don't know yet
+ InPort // are in port
+ }
+
+ let len = rawurl.len();
+ let mut st = Start;
+ let mut input = Digit; // most restricted, start here.
+
+ let mut userinfo = None;
+ let mut host = ~"";
+ let mut port = None;
+
+ let mut colon_count = 0;
+ let mut pos = 0;
+ let mut begin = 2;
+ let mut end = len;
+
+ for (i,c) in rawurl.chars().enumerate() {
+ if i < 2 { continue; } // ignore the leading //
+
+ // deal with input class first
+ match c {
+ '0' .. '9' => (),
+ 'A' .. 'F' | 'a' .. 'f' => {
+ if input == Digit {
+ input = Hex;
+ }
+ }
+ 'G' .. 'Z' | 'g' .. 'z' | '-' | '.' | '_' | '~' | '%' |
+ '&' |'\'' | '(' | ')' | '+' | '!' | '*' | ',' | ';' | '=' => {
+ input = Unreserved;
+ }
+ ':' | '@' | '?' | '#' | '/' => {
+ // separators, don't change anything
+ }
+ _ => {
+ return Err(~"Illegal character in authority");
+ }
+ }
+
+ // now process states
+ match c {
+ ':' => {
+ colon_count += 1;
+ match st {
+ Start => {
+ pos = i;
+ st = PassHostPort;
+ }
+ PassHostPort => {
+ // multiple colons means ipv6 address.
+ if input == Unreserved {
+ return Err(
+ ~"Illegal characters in IPv6 address.");
+ }
+ st = Ip6Host;
+ }
+ InHost => {
+ pos = i;
+ if input == Unreserved {
+ // must be port
+ host = rawurl.slice(begin, i).to_owned();
+ st = InPort;
+ } else {
+ // can't be sure whether this is an ipv6 address or a port
+ st = Ip6Port;
+ }
+ }
+ Ip6Port => {
+ if input == Unreserved {
+ return Err(~"Illegal characters in authority.");
+ }
+ st = Ip6Host;
+ }
+ Ip6Host => {
+ if colon_count > 7 {
+ host = rawurl.slice(begin, i).to_owned();
+ pos = i;
+ st = InPort;
+ }
+ }
+ _ => {
+ return Err(~"Invalid ':' in authority.");
+ }
+ }
+ input = Digit; // reset input class
+ }
+
+ '@' => {
+ input = Digit; // reset input class
+ colon_count = 0; // reset count
+ match st {
+ Start => {
+ let user = rawurl.slice(begin, i).to_owned();
+ userinfo = Some(UserInfo::new(user, None));
+ st = InHost;
+ }
+ PassHostPort => {
+ let user = rawurl.slice(begin, pos).to_owned();
+ let pass = rawurl.slice(pos+1, i).to_owned();
+ userinfo = Some(UserInfo::new(user, Some(pass)));
+ st = InHost;
+ }
+ _ => {
+ return Err(~"Invalid '@' in authority.");
+ }
+ }
+ begin = i+1;
+ }
+
+ '?' | '#' | '/' => {
+ end = i;
+ break;
+ }
+ _ => ()
+ }
+ }
+
+ // finish up
+ match st {
+ Start => {
+ host = rawurl.slice(begin, end).to_owned();
+ }
+ PassHostPort | Ip6Port => {
+ if input != Digit {
+ return Err(~"Non-digit characters in port.");
+ }
+ host = rawurl.slice(begin, pos).to_owned();
+ port = Some(rawurl.slice(pos+1, end).to_owned());
+ }
+ Ip6Host | InHost => {
+ host = rawurl.slice(begin, end).to_owned();
+ }
+ InPort => {
+ if input != Digit {
+ return Err(~"Non-digit characters in port.");
+ }
+ port = Some(rawurl.slice(pos+1, end).to_owned());
+ }
+ }
+
+ let rest = rawurl.slice(end, len).to_owned();
+ return Ok((userinfo, host, port, rest));
+}
+
+
+// returns the path and unparsed part of url, or an error
+fn get_path(rawurl: &str, authority: bool) ->
+ Result<(~str, ~str), ~str> {
+ let len = rawurl.len();
+ let mut end = len;
+ for (i,c) in rawurl.chars().enumerate() {
+ match c {
+ 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '&' |'\'' | '(' | ')' | '.'
+ | '@' | ':' | '%' | '/' | '+' | '!' | '*' | ',' | ';' | '='
+ | '_' | '-' | '~' => {
+ continue;
+ }
+ '?' | '#' => {
+ end = i;
+ break;
+ }
+ _ => return Err(~"Invalid character in path.")
+ }
+ }
+
+ if authority {
+ if end != 0 && !rawurl.starts_with("/") {
+ return Err(~"Non-empty path must begin with\
+ '/' in presence of authority.");
+ }
+ }
+
+ return Ok((decode_component(rawurl.slice(0, end)),
+ rawurl.slice(end, len).to_owned()));
+}
+
+// returns the parsed query and the fragment, if present
+fn get_query_fragment(rawurl: &str) ->
+ Result<(Query, Option<~str>), ~str> {
+ if !rawurl.starts_with("?") {
+ if rawurl.starts_with("#") {
+ let f = decode_component(rawurl.slice(
+ 1,
+ rawurl.len()));
+ return Ok((vec!(), Some(f)));
+ } else {
+ return Ok((vec!(), None));
+ }
+ }
+ let (q, r) = split_char_first(rawurl.slice(1, rawurl.len()), '#');
+ let f = if r.len() != 0 {
+ Some(decode_component(r)) } else { None };
+ return Ok((query_from_str(q), f));
+}
+
+/**
+ * Parses a URL, converting it from a string to `Url` representation.
+ *
+ * # Arguments
+ *
+ * `rawurl` - a string representing the full URL, including scheme.
+ *
+ * # Returns
+ *
+ * A `Url` struct type representing the URL.
+ */
+pub fn from_str(rawurl: &str) -> Result<Url, ~str> {
+ // scheme
+ let (scheme, rest) = match get_scheme(rawurl) {
+ Ok(val) => val,
+ Err(e) => return Err(e),
+ };
+
+ // authority
+ let (userinfo, host, port, rest) = match get_authority(rest) {
+ Ok(val) => val,
+ Err(e) => return Err(e),
+ };
+
+ // path
+ let has_authority = if host == ~"" { false } else { true };
+ let (path, rest) = match get_path(rest, has_authority) {
+ Ok(val) => val,
+ Err(e) => return Err(e),
+ };
+
+ // query and fragment
+ let (query, fragment) = match get_query_fragment(rest) {
+ Ok(val) => val,
+ Err(e) => return Err(e),
+ };
+
+ Ok(Url::new(scheme, userinfo, host, port, path, query, fragment))
+}
+
+pub fn path_from_str(rawpath: &str) -> Result<Path, ~str> {
+ let (path, rest) = match get_path(rawpath, false) {
+ Ok(val) => val,
+ Err(e) => return Err(e)
+ };
+
+ // query and fragment
+ let (query, fragment) = match get_query_fragment(rest) {
+ Ok(val) => val,
+ Err(e) => return Err(e),
+ };
+
+ Ok(Path{ path: path, query: query, fragment: fragment })
+}
+
+impl FromStr for Url {
+ fn from_str(s: &str) -> Option<Url> {
+ match from_str(s) {
+ Ok(url) => Some(url),
+ Err(_) => None
+ }
+ }
+}
+
+impl FromStr for Path {
+ fn from_str(s: &str) -> Option<Path> {
+ match path_from_str(s) {
+ Ok(path) => Some(path),
+ Err(_) => None
+ }
+ }
+}
+
+impl fmt::Show for Url {
+ /**
+ * Converts a URL from `Url` to string representation.
+ *
+ * # Arguments
+ *
+ * `url` - a URL.
+ *
+ * # Returns
+ *
+ * A string that contains the formatted URL. Note that this will usually
+ * be an inverse of `from_str` but might strip out unneeded separators;
+ * for example, "http://somehost.com?", when parsed and formatted, will
+ * result in just "http://somehost.com".
+ */
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ try!(write!(f.buf, "{}:", self.scheme));
+
+ if !self.host.is_empty() {
+ try!(write!(f.buf, "//"));
+ match self.user {
+ Some(ref user) => try!(write!(f.buf, "{}", *user)),
+ None => {}
+ }
+ match self.port {
+ Some(ref port) => try!(write!(f.buf, "{}:{}", self.host,
+ *port)),
+ None => try!(write!(f.buf, "{}", self.host)),
+ }
+ }
+
+ try!(write!(f.buf, "{}", self.path));
+
+ if !self.query.is_empty() {
+ try!(write!(f.buf, "?{}", query_to_str(&self.query)));
+ }
+
+ match self.fragment {
+ Some(ref fragment) => write!(f.buf, "\\#{}",
+ encode_component(*fragment)),
+ None => Ok(()),
+ }
+ }
+}
+
+impl fmt::Show for Path {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ try!(write!(f.buf, "{}", self.path));
+ if !self.query.is_empty() {
+ try!(write!(f.buf, "?{}", self.query))
+ }
+
+ match self.fragment {
+ Some(ref fragment) => {
+ write!(f.buf, "\\#{}", encode_component(*fragment))
+ }
+ None => Ok(())
+ }
+ }
+}
+
+impl<S: Writer> Hash<S> for Url {
+ fn hash(&self, state: &mut S) {
+ self.to_str().hash(state)
+ }
+}
+
+impl<S: Writer> Hash<S> for Path {
+ fn hash(&self, state: &mut S) {
+ self.to_str().hash(state)
+ }
+}
+
+// Put a few tests outside of the 'test' module so they can test the internal
+// functions and those functions don't need 'pub'
+
+#[test]
+fn test_split_char_first() {
+ let (u,v) = split_char_first("hello, sweet world", ',');
+ assert_eq!(u, ~"hello");
+ assert_eq!(v, ~" sweet world");
+
+ let (u,v) = split_char_first("hello sweet world", ',');
+ assert_eq!(u, ~"hello sweet world");
+ assert_eq!(v, ~"");
+}
+
+#[test]
+fn test_get_authority() {
+ let (u, h, p, r) = get_authority(
+ "//user:pass@rust-lang.org/something").unwrap();
+ assert_eq!(u, Some(UserInfo::new(~"user", Some(~"pass"))));
+ assert_eq!(h, ~"rust-lang.org");
+ assert!(p.is_none());
+ assert_eq!(r, ~"/something");
+
+ let (u, h, p, r) = get_authority(
+ "//rust-lang.org:8000?something").unwrap();
+ assert!(u.is_none());
+ assert_eq!(h, ~"rust-lang.org");
+ assert_eq!(p, Some(~"8000"));
+ assert_eq!(r, ~"?something");
+
+ let (u, h, p, r) = get_authority(
+ "//rust-lang.org#blah").unwrap();
+ assert!(u.is_none());
+ assert_eq!(h, ~"rust-lang.org");
+ assert!(p.is_none());
+ assert_eq!(r, ~"#blah");
+
+ // ipv6 tests
+ let (_, h, _, _) = get_authority(
+ "//2001:0db8:85a3:0042:0000:8a2e:0370:7334#blah").unwrap();
+ assert_eq!(h, ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334");
+
+ let (_, h, p, _) = get_authority(
+ "//2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000#blah").unwrap();
+ assert_eq!(h, ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334");
+ assert_eq!(p, Some(~"8000"));
+
+ let (u, h, p, _) = get_authority(
+ "//us:p@2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000#blah"
+ ).unwrap();
+ assert_eq!(u, Some(UserInfo::new(~"us", Some(~"p"))));
+ assert_eq!(h, ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334");
+ assert_eq!(p, Some(~"8000"));
+
+ // invalid authorities;
+ assert!(get_authority("//user:pass@rust-lang:something").is_err());
+ assert!(get_authority("//user@rust-lang:something:/path").is_err());
+ assert!(get_authority(
+ "//2001:0db8:85a3:0042:0000:8a2e:0370:7334:800a").is_err());
+ assert!(get_authority(
+ "//2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000:00").is_err());
+
+ // these parse as empty, because they don't start with '//'
+ let (_, h, _, _) = get_authority("user:pass@rust-lang").unwrap();
+ assert_eq!(h, ~"");
+ let (_, h, _, _) = get_authority("rust-lang.org").unwrap();
+ assert_eq!(h, ~"");
+}
+
+#[test]
+fn test_get_path() {
+ let (p, r) = get_path("/something+%20orother", true).unwrap();
+ assert_eq!(p, ~"/something+ orother");
+ assert_eq!(r, ~"");
+ let (p, r) = get_path("test@email.com#fragment", false).unwrap();
+ assert_eq!(p, ~"test@email.com");
+ assert_eq!(r, ~"#fragment");
+ let (p, r) = get_path("/gen/:addr=?q=v", false).unwrap();
+ assert_eq!(p, ~"/gen/:addr=");
+ assert_eq!(r, ~"?q=v");
+
+ //failure cases
+ assert!(get_path("something?q", true).is_err());
+}
+
+#[cfg(test)]
+mod tests {
+ use {encode_form_urlencoded, decode_form_urlencoded,
+ decode, encode, from_str, encode_component, decode_component,
+ path_from_str, UserInfo, get_scheme};
+
+ use collections::HashMap;
+
+ #[test]
+ fn test_url_parse() {
+ let url = ~"http://user:pass@rust-lang.org:8080/doc/~u?s=v#something";
+
+ let up = from_str(url);
+ let u = up.unwrap();
+ assert_eq!(&u.scheme, &~"http");
+ assert_eq!(&u.user, &Some(UserInfo::new(~"user", Some(~"pass"))));
+ assert_eq!(&u.host, &~"rust-lang.org");
+ assert_eq!(&u.port, &Some(~"8080"));
+ assert_eq!(&u.path, &~"/doc/~u");
+ assert_eq!(&u.query, &vec!((~"s", ~"v")));
+ assert_eq!(&u.fragment, &Some(~"something"));
+ }
+
+ #[test]
+ fn test_path_parse() {
+ let path = ~"/doc/~u?s=v#something";
+
+ let up = path_from_str(path);
+ let u = up.unwrap();
+ assert_eq!(&u.path, &~"/doc/~u");
+ assert_eq!(&u.query, &vec!((~"s", ~"v")));
+ assert_eq!(&u.fragment, &Some(~"something"));
+ }
+
+ #[test]
+ fn test_url_parse_host_slash() {
+ let urlstr = ~"http://0.42.42.42/";
+ let url = from_str(urlstr).unwrap();
+ assert!(url.host == ~"0.42.42.42");
+ assert!(url.path == ~"/");
+ }
+
+ #[test]
+ fn test_path_parse_host_slash() {
+ let pathstr = ~"/";
+ let path = path_from_str(pathstr).unwrap();
+ assert!(path.path == ~"/");
+ }
+
+ #[test]
+ fn test_url_host_with_port() {
+ let urlstr = ~"scheme://host:1234";
+ let url = from_str(urlstr).unwrap();
+ assert_eq!(&url.scheme, &~"scheme");
+ assert_eq!(&url.host, &~"host");
+ assert_eq!(&url.port, &Some(~"1234"));
+ assert_eq!(&url.path, &~""); // is empty path really correct? Other tests think so
+ let urlstr = ~"scheme://host:1234/";
+ let url = from_str(urlstr).unwrap();
+ assert_eq!(&url.scheme, &~"scheme");
+ assert_eq!(&url.host, &~"host");
+ assert_eq!(&url.port, &Some(~"1234"));
+ assert_eq!(&url.path, &~"/");
+ }
+
+ #[test]
+ fn test_url_with_underscores() {
+ let urlstr = ~"http://dotcom.com/file_name.html";
+ let url = from_str(urlstr).unwrap();
+ assert!(url.path == ~"/file_name.html");
+ }
+
+ #[test]
+ fn test_path_with_underscores() {
+ let pathstr = ~"/file_name.html";
+ let path = path_from_str(pathstr).unwrap();
+ assert!(path.path == ~"/file_name.html");
+ }
+
+ #[test]
+ fn test_url_with_dashes() {
+ let urlstr = ~"http://dotcom.com/file-name.html";
+ let url = from_str(urlstr).unwrap();
+ assert!(url.path == ~"/file-name.html");
+ }
+
+ #[test]
+ fn test_path_with_dashes() {
+ let pathstr = ~"/file-name.html";
+ let path = path_from_str(pathstr).unwrap();
+ assert!(path.path == ~"/file-name.html");
+ }
+
+ #[test]
+ fn test_no_scheme() {
+ assert!(get_scheme("noschemehere.html").is_err());
+ }
+
+ #[test]
+ fn test_invalid_scheme_errors() {
+ assert!(from_str("99://something").is_err());
+ assert!(from_str("://something").is_err());
+ }
+
+ #[test]
+ fn test_full_url_parse_and_format() {
+ let url = ~"http://user:pass@rust-lang.org/doc?s=v#something";
+ assert_eq!(from_str(url).unwrap().to_str(), url);
+ }
+
+ #[test]
+ fn test_userless_url_parse_and_format() {
+ let url = ~"http://rust-lang.org/doc?s=v#something";
+ assert_eq!(from_str(url).unwrap().to_str(), url);
+ }
+
+ #[test]
+ fn test_queryless_url_parse_and_format() {
+ let url = ~"http://user:pass@rust-lang.org/doc#something";
+ assert_eq!(from_str(url).unwrap().to_str(), url);
+ }
+
+ #[test]
+ fn test_empty_query_url_parse_and_format() {
+ let url = ~"http://user:pass@rust-lang.org/doc?#something";
+ let should_be = ~"http://user:pass@rust-lang.org/doc#something";
+ assert_eq!(from_str(url).unwrap().to_str(), should_be);
+ }
+
+ #[test]
+ fn test_fragmentless_url_parse_and_format() {
+ let url = ~"http://user:pass@rust-lang.org/doc?q=v";
+ assert_eq!(from_str(url).unwrap().to_str(), url);
+ }
+
+ #[test]
+ fn test_minimal_url_parse_and_format() {
+ let url = ~"http://rust-lang.org/doc";
+ assert_eq!(from_str(url).unwrap().to_str(), url);
+ }
+
+ #[test]
+ fn test_url_with_port_parse_and_format() {
+ let url = ~"http://rust-lang.org:80/doc";
+ assert_eq!(from_str(url).unwrap().to_str(), url);
+ }
+
+ #[test]
+ fn test_scheme_host_only_url_parse_and_format() {
+ let url = ~"http://rust-lang.org";
+ assert_eq!(from_str(url).unwrap().to_str(), url);
+ }
+
+ #[test]
+ fn test_pathless_url_parse_and_format() {
+ let url = ~"http://user:pass@rust-lang.org?q=v#something";
+ assert_eq!(from_str(url).unwrap().to_str(), url);
+ }
+
+ #[test]
+ fn test_scheme_host_fragment_only_url_parse_and_format() {
+ let url = ~"http://rust-lang.org#something";
+ assert_eq!(from_str(url).unwrap().to_str(), url);
+ }
+
+ #[test]
+ fn test_url_component_encoding() {
+ let url = ~"http://rust-lang.org/doc%20uments?ba%25d%20=%23%26%2B";
+ let u = from_str(url).unwrap();
+ assert!(u.path == ~"/doc uments");
+ assert!(u.query == vec!((~"ba%d ", ~"#&+")));
+ }
+
+ #[test]
+ fn test_path_component_encoding() {
+ let path = ~"/doc%20uments?ba%25d%20=%23%26%2B";
+ let p = path_from_str(path).unwrap();
+ assert!(p.path == ~"/doc uments");
+ assert!(p.query == vec!((~"ba%d ", ~"#&+")));
+ }
+
+ #[test]
+ fn test_url_without_authority() {
+ let url = ~"mailto:test@email.com";
+ assert_eq!(from_str(url).unwrap().to_str(), url);
+ }
+
+ #[test]
+ fn test_encode() {
+ assert_eq!(encode(""), ~"");
+ assert_eq!(encode("http://example.com"), ~"http://example.com");
+ assert_eq!(encode("foo bar% baz"), ~"foo%20bar%25%20baz");
+ assert_eq!(encode(" "), ~"%20");
+ assert_eq!(encode("!"), ~"!");
+ assert_eq!(encode("\""), ~"\"");
+ assert_eq!(encode("#"), ~"#");
+ assert_eq!(encode("$"), ~"$");
+ assert_eq!(encode("%"), ~"%25");
+ assert_eq!(encode("&"), ~"&");
+ assert_eq!(encode("'"), ~"%27");
+ assert_eq!(encode("("), ~"(");
+ assert_eq!(encode(")"), ~")");
+ assert_eq!(encode("*"), ~"*");
+ assert_eq!(encode("+"), ~"+");
+ assert_eq!(encode(","), ~",");
+ assert_eq!(encode("/"), ~"/");
+ assert_eq!(encode(":"), ~":");
+ assert_eq!(encode(";"), ~";");
+ assert_eq!(encode("="), ~"=");
+ assert_eq!(encode("?"), ~"?");
+ assert_eq!(encode("@"), ~"@");
+ assert_eq!(encode("["), ~"[");
+ assert_eq!(encode("]"), ~"]");
+ }
+
+ #[test]
+ fn test_encode_component() {
+ assert_eq!(encode_component(""), ~"");
+ assert!(encode_component("http://example.com") ==
+ ~"http%3A%2F%2Fexample.com");
+ assert!(encode_component("foo bar% baz") ==
+ ~"foo%20bar%25%20baz");
+ assert_eq!(encode_component(" "), ~"%20");
+ assert_eq!(encode_component("!"), ~"%21");
+ assert_eq!(encode_component("#"), ~"%23");
+ assert_eq!(encode_component("$"), ~"%24");
+ assert_eq!(encode_component("%"), ~"%25");
+ assert_eq!(encode_component("&"), ~"%26");
+ assert_eq!(encode_component("'"), ~"%27");
+ assert_eq!(encode_component("("), ~"%28");
+ assert_eq!(encode_component(")"), ~"%29");
+ assert_eq!(encode_component("*"), ~"%2A");
+ assert_eq!(encode_component("+"), ~"%2B");
+ assert_eq!(encode_component(","), ~"%2C");
+ assert_eq!(encode_component("/"), ~"%2F");
+ assert_eq!(encode_component(":"), ~"%3A");
+ assert_eq!(encode_component(";"), ~"%3B");
+ assert_eq!(encode_component("="), ~"%3D");
+ assert_eq!(encode_component("?"), ~"%3F");
+ assert_eq!(encode_component("@"), ~"%40");
+ assert_eq!(encode_component("["), ~"%5B");
+ assert_eq!(encode_component("]"), ~"%5D");
+ }
+
+ #[test]
+ fn test_decode() {
+ assert_eq!(decode(""), ~"");
+ assert_eq!(decode("abc/def 123"), ~"abc/def 123");
+ assert_eq!(decode("abc%2Fdef%20123"), ~"abc%2Fdef 123");
+ assert_eq!(decode("%20"), ~" ");
+ assert_eq!(decode("%21"), ~"%21");
+ assert_eq!(decode("%22"), ~"%22");
+ assert_eq!(decode("%23"), ~"%23");
+ assert_eq!(decode("%24"), ~"%24");
+ assert_eq!(decode("%25"), ~"%");
+ assert_eq!(decode("%26"), ~"%26");
+ assert_eq!(decode("%27"), ~"'");
+ assert_eq!(decode("%28"), ~"%28");
+ assert_eq!(decode("%29"), ~"%29");
+ assert_eq!(decode("%2A"), ~"%2A");
+ assert_eq!(decode("%2B"), ~"%2B");
+ assert_eq!(decode("%2C"), ~"%2C");
+ assert_eq!(decode("%2F"), ~"%2F");
+ assert_eq!(decode("%3A"), ~"%3A");
+ assert_eq!(decode("%3B"), ~"%3B");
+ assert_eq!(decode("%3D"), ~"%3D");
+ assert_eq!(decode("%3F"), ~"%3F");
+ assert_eq!(decode("%40"), ~"%40");
+ assert_eq!(decode("%5B"), ~"%5B");
+ assert_eq!(decode("%5D"), ~"%5D");
+ }
+
+ #[test]
+ fn test_decode_component() {
+ assert_eq!(decode_component(""), ~"");
+ assert_eq!(decode_component("abc/def 123"), ~"abc/def 123");
+ assert_eq!(decode_component("abc%2Fdef%20123"), ~"abc/def 123");
+ assert_eq!(decode_component("%20"), ~" ");
+ assert_eq!(decode_component("%21"), ~"!");
+ assert_eq!(decode_component("%22"), ~"\"");
+ assert_eq!(decode_component("%23"), ~"#");
+ assert_eq!(decode_component("%24"), ~"$");
+ assert_eq!(decode_component("%25"), ~"%");
+ assert_eq!(decode_component("%26"), ~"&");
+ assert_eq!(decode_component("%27"), ~"'");
+ assert_eq!(decode_component("%28"), ~"(");
+ assert_eq!(decode_component("%29"), ~")");
+ assert_eq!(decode_component("%2A"), ~"*");
+ assert_eq!(decode_component("%2B"), ~"+");
+ assert_eq!(decode_component("%2C"), ~",");
+ assert_eq!(decode_component("%2F"), ~"/");
+ assert_eq!(decode_component("%3A"), ~":");
+ assert_eq!(decode_component("%3B"), ~";");
+ assert_eq!(decode_component("%3D"), ~"=");
+ assert_eq!(decode_component("%3F"), ~"?");
+ assert_eq!(decode_component("%40"), ~"@");
+ assert_eq!(decode_component("%5B"), ~"[");
+ assert_eq!(decode_component("%5D"), ~"]");
+ }
+
+ #[test]
+ fn test_encode_form_urlencoded() {
+ let mut m = HashMap::new();
+ assert_eq!(encode_form_urlencoded(&m), ~"");
+
+ m.insert(~"", vec!());
+ m.insert(~"foo", vec!());
+ assert_eq!(encode_form_urlencoded(&m), ~"");
+
+ let mut m = HashMap::new();
+ m.insert(~"foo", vec!(~"bar", ~"123"));
+ assert_eq!(encode_form_urlencoded(&m), ~"foo=bar&foo=123");
+
+ let mut m = HashMap::new();
+ m.insert(~"foo bar", vec!(~"abc", ~"12 = 34"));
+ assert!(encode_form_urlencoded(&m) ==
+ ~"foo+bar=abc&foo+bar=12+%3D+34");
+ }
+
+ #[test]
+ fn test_decode_form_urlencoded() {
+ assert_eq!(decode_form_urlencoded([]).len(), 0);
+
+ let s = "a=1&foo+bar=abc&foo+bar=12+%3D+34".as_bytes();
+ let form = decode_form_urlencoded(s);
+ assert_eq!(form.len(), 2);
+ assert_eq!(form.get(&~"a"), &vec!(~"1"));
+ assert_eq!(form.get(&~"foo bar"), &vec!(~"abc", ~"12 = 34"));
+ }
+}
#[crate_type = "rlib"];
#[crate_type = "dylib"];
#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
+
+#[allow(deprecated_owned_vector)];
#[feature(default_type_params)];
--- /dev/null
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[crate_id = "workcache#0.10-pre"];
+#[crate_type = "rlib"];
+#[crate_type = "dylib"];
+#[license = "MIT/ASL2"];
+#[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+ html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+ html_root_url = "http://static.rust-lang.org/doc/master")];
+#[feature(phase)];
+#[allow(deprecated_owned_vector, visible_private_types)];
+
+#[phase(syntax, link)] extern crate log;
+extern crate serialize;
+extern crate collections;
+extern crate sync;
+
+use serialize::json;
+use serialize::json::ToJson;
+use serialize::{Encoder, Encodable, Decoder, Decodable};
+use sync::{Arc,RWArc};
+use collections::TreeMap;
+use std::str;
+use std::io;
+use std::io::{File, MemWriter};
+
+/**
+*
+* This is a loose clone of the [fbuild build system](https://github.com/felix-lang/fbuild),
+* made a touch more generic (not wired to special cases on files) and much
+* less metaprogram-y due to rust's comparative weakness there, relative to
+* python.
+*
+* It's based around _imperative builds_ that happen to have some function
+* calls cached. That is, it's _just_ a mechanism for describing cached
+* functions. This makes it much simpler and smaller than a "build system"
+* that produces an IR and evaluates it. The evaluation order is normal
+* function calls. Some of them just return really quickly.
+*
+* A cached function consumes and produces a set of _works_. A work has a
+* name, a kind (that determines how the value is to be checked for
+* freshness) and a value. Works must also be (de)serializable. Some
+* examples of works:
+*
+* kind name value
+* ------------------------
+* cfg os linux
+* file foo.c <sha1>
+* url foo.com <etag>
+*
+* Works are conceptually single units, but we store them most of the time
+* in maps of the form (type,name) => value. These are WorkMaps.
+*
+* A cached function divides the works it's interested in into inputs and
+* outputs, and subdivides those into declared (input) works and
+* discovered (input and output) works.
+*
+* A _declared_ input or is one that is given to the workcache before
+* any work actually happens, in the "prep" phase. Even when a function's
+* work-doing part (the "exec" phase) never gets called, it has declared
+* inputs, which can be checked for freshness (and potentially
+* used to determine that the function can be skipped).
+*
+* The workcache checks _all_ works for freshness, but uses the set of
+* discovered outputs from the _previous_ exec (which it will re-discover
+* and re-record each time the exec phase runs).
+*
+* Therefore the discovered works cached in the db might be a
+* mis-approximation of the current discoverable works, but this is ok for
+* the following reason: we assume that if an artifact A changed from
+* depending on B,C,D to depending on B,C,D,E, then A itself changed (as
+* part of the change-in-dependencies), so we will be ok.
+*
+* Each function has a single discriminated output work called its _result_.
+* This is only different from other works in that it is returned, by value,
+* from a call to the cacheable function; the other output works are used in
+* passing to invalidate dependencies elsewhere in the cache, but do not
+* otherwise escape from a function invocation. Most functions only have one
+* output work anyways.
+*
+* A database (the central store of a workcache) stores a mappings:
+*
+* (fn_name,{declared_input}) => ({discovered_input},
+* {discovered_output},result)
+*
+* (Note: fbuild, which workcache is based on, has the concept of a declared
+* output as separate from a discovered output. This distinction exists only
+* as an artifact of how fbuild works: via annotations on function types
+* and metaprogramming, with explicit dependency declaration as a fallback.
+* Workcache is more explicit about dependencies, and as such treats all
+* outputs the same, as discovered-during-the-last-run.)
+*
+*/
+
+#[deriving(Clone, Eq, Encodable, Decodable, Ord, TotalOrd, TotalEq)]
+struct WorkKey {
+ kind: ~str,
+ name: ~str
+}
+
+impl WorkKey {
+ pub fn new(kind: &str, name: &str) -> WorkKey {
+ WorkKey {
+ kind: kind.to_owned(),
+ name: name.to_owned(),
+ }
+ }
+}
+
+// FIXME #8883: The key should be a WorkKey and not a ~str.
+// This is working around some JSON weirdness.
+#[deriving(Clone, Eq, Encodable, Decodable)]
+struct WorkMap(TreeMap<~str, KindMap>);
+
+#[deriving(Clone, Eq, Encodable, Decodable)]
+struct KindMap(TreeMap<~str, ~str>);
+
+impl WorkMap {
+ fn new() -> WorkMap { WorkMap(TreeMap::new()) }
+
+ fn insert_work_key(&mut self, k: WorkKey, val: ~str) {
+ let WorkKey { kind, name } = k;
+ let WorkMap(ref mut map) = *self;
+ match map.find_mut(&name) {
+ Some(&KindMap(ref mut m)) => { m.insert(kind, val); return; }
+ None => ()
+ }
+ let mut new_map = TreeMap::new();
+ new_map.insert(kind, val);
+ map.insert(name, KindMap(new_map));
+ }
+}
+
+pub struct Database {
+ priv db_filename: Path,
+ priv db_cache: TreeMap<~str, ~str>,
+ db_dirty: bool
+}
+
+impl Database {
+
+ pub fn new(p: Path) -> Database {
+ let mut rslt = Database {
+ db_filename: p,
+ db_cache: TreeMap::new(),
+ db_dirty: false
+ };
+ if rslt.db_filename.exists() {
+ rslt.load();
+ }
+ rslt
+ }
+
+ pub fn prepare(&self,
+ fn_name: &str,
+ declared_inputs: &WorkMap)
+ -> Option<(WorkMap, WorkMap, ~str)> {
+ let k = json_encode(&(fn_name, declared_inputs));
+ match self.db_cache.find(&k) {
+ None => None,
+ Some(v) => Some(json_decode(*v))
+ }
+ }
+
+ pub fn cache(&mut self,
+ fn_name: &str,
+ declared_inputs: &WorkMap,
+ discovered_inputs: &WorkMap,
+ discovered_outputs: &WorkMap,
+ result: &str) {
+ let k = json_encode(&(fn_name, declared_inputs));
+ let v = json_encode(&(discovered_inputs,
+ discovered_outputs,
+ result));
+ self.db_cache.insert(k,v);
+ self.db_dirty = true
+ }
+
+ // FIXME #4330: This should have &mut self and should set self.db_dirty to false.
+ fn save(&self) -> io::IoResult<()> {
+ let mut f = File::create(&self.db_filename);
+ self.db_cache.to_json().to_pretty_writer(&mut f)
+ }
+
+ fn load(&mut self) {
+ assert!(!self.db_dirty);
+ assert!(self.db_filename.exists());
+ match File::open(&self.db_filename) {
+ Err(e) => fail!("Couldn't load workcache database {}: {}",
+ self.db_filename.display(),
+ e),
+ Ok(mut stream) => {
+ match json::from_reader(&mut stream) {
+ Err(e) => fail!("Couldn't parse workcache database (from file {}): {}",
+ self.db_filename.display(), e.to_str()),
+ Ok(r) => {
+ let mut decoder = json::Decoder::new(r);
+ self.db_cache = Decodable::decode(&mut decoder);
+ }
+ }
+ }
+ }
+ }
+}
+
+#[unsafe_destructor]
+impl Drop for Database {
+ fn drop(&mut self) {
+ if self.db_dirty {
+ // FIXME: is failing the right thing to do here
+ self.save().unwrap();
+ }
+ }
+}
+
+pub type FreshnessMap = TreeMap<~str,extern fn(&str,&str)->bool>;
+
+#[deriving(Clone)]
+pub struct Context {
+ db: RWArc<Database>,
+ priv cfg: Arc<json::Object>,
+ /// Map from kinds (source, exe, url, etc.) to a freshness function.
+ /// The freshness function takes a name (e.g. file path) and value
+ /// (e.g. hash of file contents) and determines whether it's up-to-date.
+ /// For example, in the file case, this would read the file off disk,
+ /// hash it, and return the result of comparing the given hash and the
+ /// read hash for equality.
+ priv freshness: Arc<FreshnessMap>
+}
+
+pub struct Prep<'a> {
+ priv ctxt: &'a Context,
+ priv fn_name: &'a str,
+ priv declared_inputs: WorkMap,
+}
+
+pub struct Exec {
+ priv discovered_inputs: WorkMap,
+ priv discovered_outputs: WorkMap
+}
+
+enum Work<'a, T> {
+ WorkValue(T),
+ WorkFromTask(&'a Prep<'a>, Receiver<(Exec, T)>),
+}
+
+fn json_encode<'a, T:Encodable<json::Encoder<'a>>>(t: &T) -> ~str {
+ let mut writer = MemWriter::new();
+ let mut encoder = json::Encoder::new(&mut writer as &mut io::Writer);
+ t.encode(&mut encoder);
+ str::from_utf8_owned(writer.unwrap()).unwrap()
+}
+
+// FIXME(#5121)
+fn json_decode<T:Decodable<json::Decoder>>(s: &str) -> T {
+ debug!("json decoding: {}", s);
+ let j = json::from_str(s).unwrap();
+ let mut decoder = json::Decoder::new(j);
+ Decodable::decode(&mut decoder)
+}
+
+impl Context {
+
+ pub fn new(db: RWArc<Database>,
+ cfg: Arc<json::Object>) -> Context {
+ Context::new_with_freshness(db, cfg, Arc::new(TreeMap::new()))
+ }
+
+ pub fn new_with_freshness(db: RWArc<Database>,
+ cfg: Arc<json::Object>,
+ freshness: Arc<FreshnessMap>) -> Context {
+ Context {
+ db: db,
+ cfg: cfg,
+ freshness: freshness
+ }
+ }
+
+ pub fn prep<'a>(&'a self, fn_name: &'a str) -> Prep<'a> {
+ Prep::new(self, fn_name)
+ }
+
+ pub fn with_prep<'a,
+ T>(
+ &'a self,
+ fn_name: &'a str,
+ blk: |p: &mut Prep| -> T)
+ -> T {
+ let mut p = self.prep(fn_name);
+ blk(&mut p)
+ }
+
+}
+
+impl Exec {
+ pub fn discover_input(&mut self,
+ dependency_kind: &str,
+ dependency_name: &str,
+ dependency_val: &str) {
+ debug!("Discovering input {} {} {}", dependency_kind, dependency_name, dependency_val);
+ self.discovered_inputs.insert_work_key(WorkKey::new(dependency_kind, dependency_name),
+ dependency_val.to_owned());
+ }
+ pub fn discover_output(&mut self,
+ dependency_kind: &str,
+ dependency_name: &str,
+ dependency_val: &str) {
+ debug!("Discovering output {} {} {}", dependency_kind, dependency_name, dependency_val);
+ self.discovered_outputs.insert_work_key(WorkKey::new(dependency_kind, dependency_name),
+ dependency_val.to_owned());
+ }
+
+ // returns pairs of (kind, name)
+ pub fn lookup_discovered_inputs(&self) -> ~[(~str, ~str)] {
+ let mut rs = ~[];
+ let WorkMap(ref discovered_inputs) = self.discovered_inputs;
+ for (k, v) in discovered_inputs.iter() {
+ let KindMap(ref vmap) = *v;
+ for (k1, _) in vmap.iter() {
+ rs.push((k1.clone(), k.clone()));
+ }
+ }
+ rs
+ }
+}
+
+impl<'a> Prep<'a> {
+ fn new(ctxt: &'a Context, fn_name: &'a str) -> Prep<'a> {
+ Prep {
+ ctxt: ctxt,
+ fn_name: fn_name,
+ declared_inputs: WorkMap::new()
+ }
+ }
+
+ pub fn lookup_declared_inputs(&self) -> ~[~str] {
+ let mut rs = ~[];
+ let WorkMap(ref declared_inputs) = self.declared_inputs;
+ for (_, v) in declared_inputs.iter() {
+ let KindMap(ref vmap) = *v;
+ for (inp, _) in vmap.iter() {
+ rs.push(inp.clone());
+ }
+ }
+ rs
+ }
+}
+
+impl<'a> Prep<'a> {
+ pub fn declare_input(&mut self, kind: &str, name: &str, val: &str) {
+ debug!("Declaring input {} {} {}", kind, name, val);
+ self.declared_inputs.insert_work_key(WorkKey::new(kind, name),
+ val.to_owned());
+ }
+
+ fn is_fresh(&self, cat: &str, kind: &str,
+ name: &str, val: &str) -> bool {
+ let k = kind.to_owned();
+ let f = self.ctxt.freshness.get().find(&k);
+ debug!("freshness for: {}/{}/{}/{}", cat, kind, name, val)
+ let fresh = match f {
+ None => fail!("missing freshness-function for '{}'", kind),
+ Some(f) => (*f)(name, val)
+ };
+ if fresh {
+ info!("{} {}:{} is fresh", cat, kind, name);
+ } else {
+ info!("{} {}:{} is not fresh", cat, kind, name);
+ }
+ fresh
+ }
+
+ fn all_fresh(&self, cat: &str, map: &WorkMap) -> bool {
+ let WorkMap(ref map) = *map;
+ for (k_name, kindmap) in map.iter() {
+ let KindMap(ref kindmap_) = *kindmap;
+ for (k_kind, v) in kindmap_.iter() {
+ if ! self.is_fresh(cat, *k_kind, *k_name, *v) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ pub fn exec<'a, T:Send +
+ Encodable<json::Encoder<'a>> +
+ Decodable<json::Decoder>>(
+ &'a self, blk: proc(&mut Exec) -> T) -> T {
+ self.exec_work(blk).unwrap()
+ }
+
+ fn exec_work<'a, T:Send +
+ Encodable<json::Encoder<'a>> +
+ Decodable<json::Decoder>>( // FIXME(#5121)
+ &'a self, blk: proc(&mut Exec) -> T) -> Work<'a, T> {
+ let mut bo = Some(blk);
+
+ debug!("exec_work: looking up {} and {:?}", self.fn_name,
+ self.declared_inputs);
+ let cached = self.ctxt.db.read(|db| {
+ db.prepare(self.fn_name, &self.declared_inputs)
+ });
+
+ match cached {
+ Some((ref disc_in, ref disc_out, ref res))
+ if self.all_fresh("declared input",&self.declared_inputs) &&
+ self.all_fresh("discovered input", disc_in) &&
+ self.all_fresh("discovered output", disc_out) => {
+ debug!("Cache hit!");
+ debug!("Trying to decode: {:?} / {:?} / {}",
+ disc_in, disc_out, *res);
+ Work::from_value(json_decode(*res))
+ }
+
+ _ => {
+ debug!("Cache miss!");
+ let (tx, rx) = channel();
+ let blk = bo.take_unwrap();
+
+ // FIXME: What happens if the task fails?
+ spawn(proc() {
+ let mut exe = Exec {
+ discovered_inputs: WorkMap::new(),
+ discovered_outputs: WorkMap::new(),
+ };
+ let v = blk(&mut exe);
+ tx.send((exe, v));
+ });
+ Work::from_task(self, rx)
+ }
+ }
+ }
+}
+
+impl<'a, T:Send +
+ Encodable<json::Encoder<'a>> +
+ Decodable<json::Decoder>>
+ Work<'a, T> { // FIXME(#5121)
+
+ pub fn from_value(elt: T) -> Work<'a, T> {
+ WorkValue(elt)
+ }
+ pub fn from_task(prep: &'a Prep<'a>, port: Receiver<(Exec, T)>)
+ -> Work<'a, T> {
+ WorkFromTask(prep, port)
+ }
+
+ pub fn unwrap(self) -> T {
+ match self {
+ WorkValue(v) => v,
+ WorkFromTask(prep, port) => {
+ let (exe, v) = port.recv();
+ let s = json_encode(&v);
+ prep.ctxt.db.write(|db| {
+ db.cache(prep.fn_name,
+ &prep.declared_inputs,
+ &exe.discovered_inputs,
+ &exe.discovered_outputs,
+ s)
+ });
+ v
+ }
+ }
+ }
+}
+
+
+#[test]
+#[cfg(not(target_os="android"))] // FIXME(#10455)
+fn test() {
+ use std::os;
+ use std::io::{fs, Process};
+ use std::str::from_utf8_owned;
+
+ // Create a path to a new file 'filename' in the directory in which
+ // this test is running.
+ fn make_path(filename: ~str) -> Path {
+ let pth = os::self_exe_path().expect("workcache::test failed").with_filename(filename);
+ if pth.exists() {
+ fs::unlink(&pth).unwrap();
+ }
+ return pth;
+ }
+
+ let pth = make_path(~"foo.c");
+ File::create(&pth).write(bytes!("int main() { return 0; }")).unwrap();
+
+ let db_path = make_path(~"db.json");
+
+ let cx = Context::new(RWArc::new(Database::new(db_path)),
+ Arc::new(TreeMap::new()));
+
+ let s = cx.with_prep("test1", |prep| {
+
+ let subcx = cx.clone();
+ let pth = pth.clone();
+
+ let contents = File::open(&pth).read_to_end().unwrap();
+ let file_content = from_utf8_owned(contents).unwrap();
+
+ // FIXME (#9639): This needs to handle non-utf8 paths
+ prep.declare_input("file", pth.as_str().unwrap(), file_content);
+ prep.exec(proc(_exe) {
+ let out = make_path(~"foo.o");
+ // FIXME (#9639): This needs to handle non-utf8 paths
+ Process::status("gcc", [pth.as_str().unwrap().to_owned(),
+ ~"-o",
+ out.as_str().unwrap().to_owned()]).unwrap();
+
+ let _proof_of_concept = subcx.prep("subfn");
+ // Could run sub-rules inside here.
+
+ // FIXME (#9639): This needs to handle non-utf8 paths
+ out.as_str().unwrap().to_owned()
+ })
+ });
+
+ println!("{}", s);
+}
.set noreorder
.set nomacro
- // n.b. most of this is probably unnecessary. I know very little mips
- // assembly, and I didn't have anything to test on, so I wasn't
- // brave enough to try to trim this down.
+ addiu $29, $29, -4
+ sw $30, 0($29)
- addiu $29, $29, -12
- sw $31, 8($29)
- sw $30, 4($29)
- sw $23, 0($29)
-
- // 24 = 12 (current) + 12 (previous)
- .cfi_def_cfa_offset 24
+ // 16 = 4 (current) + 12 (previous)
+ .cfi_def_cfa_offset 16
.cfi_offset 31, -4
- .cfi_offset 30, -20
- .cfi_offset 23, -24
+ .cfi_offset 30, -16
- move $23, $28
move $30, $29
.cfi_def_cfa_register 30
- // Save argument registers of the original function
- addiu $29, $29, -32
- sw $4, 16($29)
- sw $5, 20($29)
- sw $6, 24($29)
- sw $7, 28($29)
-
- move $4, $14 // Size of stack arguments
- addu $5, $30, 24 // Address of stack arguments
- move $6, $15 // The amount of stack needed
+ // O32 ABI always reserves 16 bytes for arguments
+ addiu $29, $29, -16
- move $28, $23
- lw $25, %call16(rust_stack_exhausted)($23)
+ lw $25, %call16(rust_stack_exhausted)($28)
jalr $25
nop
pub fn eat(&mut self) -> bool {
if self.how_hungry > 0 {
- error!("OM NOM NOM");
+ println!("OM NOM NOM");
self.how_hungry -= 2;
return true;
} else {
- error!("Not hungry!");
+ println!("Not hungry!");
return false;
}
}
impl cat {
pub fn meow(&mut self) {
- error!("Meow");
+ println!("Meow");
self.meows += 1u;
if self.meows % 5u == 0u {
self.how_hungry += 1;
impl cat {
fn meow(&mut self) {
- error!("Meow");
+ println!("Meow");
self.meows += 1u;
if self.meows % 5u == 0u {
self.how_hungry += 1;
pub fn eat(&mut self) -> bool {
if self.how_hungry > 0 {
- error!("OM NOM NOM");
+ println!("OM NOM NOM");
self.how_hungry -= 2;
return true;
}
else {
- error!("Not hungry!");
+ println!("Not hungry!");
return false;
}
}
pub fn fact(n: uint) -> uint {
unsafe {
- info!("n = {}", n);
+ println!("n = {}", n);
rustrt::rust_dbg_call(cb, n)
}
}
#[crate_id="issue_2526#0.2"];
#[crate_type = "lib"];
-extern crate extra;
-
struct arc_destruct<T> {
_data: int,
}
#[crate_id="req"];
#[crate_type = "lib"];
-extern crate extra;
extern crate collections;
use std::cell::RefCell;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#[feature(phase)];
+#[phase(syntax, link)] extern crate log;
+
pub fn foo<T>() {
fn death() -> int { fail!() }
debug!("{:?}", (||{ death() })());
for i in range(0u, n) {
let x = i.to_str();
- info!("{}", x);
+ println!("{}", x);
}
}
match requests.recv_opt() {
Some(get_count) => { responses.send(count.clone()); }
Some(bytes(b)) => {
- //error!("server: received {:?} bytes", b);
+ //println!("server: received {:?} bytes", b);
count += b;
}
None => { done = true; }
}
}
responses.send(count);
- //error!("server exiting");
+ //println!("server exiting");
}
fn run(args: &[~str]) {
worker_results.push(builder.future_result());
builder.spawn(proc() {
for _ in range(0u, size / workers) {
- //error!("worker {:?}: sending {:?} bytes", i, num_bytes);
+ //println!("worker {:?}: sending {:?} bytes", i, num_bytes);
to_child.send(bytes(num_bytes));
}
- //error!("worker {:?} exiting", i);
+ //println!("worker {:?} exiting", i);
});
}
task::spawn(proc() {
r.recv();
}
- //error!("sending stop message");
+ //println!("sending stop message");
to_child.send(stop);
move_out(to_child);
let result = from_child.recv();
args.clone()
};
- info!("{:?}", args);
+ println!("{:?}", args);
run(args);
}
match requests.recv_opt() {
Some(get_count) => { responses.send(count.clone()); }
Some(bytes(b)) => {
- //error!("server: received {:?} bytes", b);
+ //println!("server: received {:?} bytes", b);
count += b;
}
None => { done = true; }
}
}
responses.send(count);
- //error!("server exiting");
+ //println!("server exiting");
}
fn run(args: &[~str]) {
worker_results.push(builder.future_result());
builder.spawn(proc() {
for _ in range(0u, size / workers) {
- //error!("worker {:?}: sending {:?} bytes", i, num_bytes);
+ //println!("worker {:?}: sending {:?} bytes", i, num_bytes);
to_child.send(bytes(num_bytes));
}
- //error!("worker {:?} exiting", i);
+ //println!("worker {:?} exiting", i);
});
from_parent
} else {
worker_results.push(builder.future_result());
builder.spawn(proc() {
for _ in range(0u, size / workers) {
- //error!("worker {:?}: sending {:?} bytes", i, num_bytes);
+ //println!("worker {:?}: sending {:?} bytes", i, num_bytes);
to_child.send(bytes(num_bytes));
}
- //error!("worker {:?} exiting", i);
+ //println!("worker {:?} exiting", i);
});
}
from_parent
r.recv();
}
- //error!("sending stop message");
+ //println!("sending stop message");
//to_child.send(stop);
//move_out(to_child);
let result = from_child.recv();
args.clone()
};
- info!("{:?}", args);
+ println!("{:?}", args);
run(args);
}
let mut num_port = Some(num_port);
// Send/Receive lots of messages.
for j in range(0u, count) {
- //error!("task %?, iter %?", i, j);
+ //println!("task %?, iter %?", i, j);
let num_chan2 = num_chan.take_unwrap();
let num_port2 = num_port.take_unwrap();
send(&num_chan2, i * j);
let mut futures = ~[];
for i in range(1u, num_tasks) {
- //error!("spawning %?", i);
+ //println!("spawning %?", i);
let (new_chan, num_port) = init();
let num_chan_2 = num_chan.clone();
let new_future = Future::spawn(proc() {
let mut num_port = Some(num_port);
// Send/Receive lots of messages.
for j in range(0u, count) {
- //error!("task %?, iter %?", i, j);
+ //println!("task %?, iter %?", i, j);
let num_chan2 = num_chan.take_unwrap();
let num_port2 = num_port.take_unwrap();
send(&num_chan2, i * j);
let mut futures = ~[];
for i in range(1u, num_tasks) {
- //error!("spawning %?", i);
+ //println!("spawning %?", i);
let (new_chan, num_port) = init();
let num_chan_2 = num_chan.clone();
let new_future = Future::spawn(proc() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::os;
use std::uint;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::os;
use std::uint;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::task::spawn;
use std::os;
use std::uint;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::os;
fn ack(m: int, n: int) -> int {
// chameneos
-extern crate extra;
-
use std::option;
use std::os;
use std::task;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::os;
fn fib(n: int) -> int {
// ignore-pretty the `let to_child` line gets an extra newline
// multi tasking k-nucleotide
-extern crate extra;
extern crate collections;
use std::cmp::Ord;
let n = 15;
assert_eq!(fib(n), fib(n));
i += 1;
- error!("{}: Completed {} iterations", id, i);
+ println!("{}: Completed {} iterations", id, i);
}
}
return;
}
token => {
- info!("thread: {} got token: {}", id, token);
+ println!("thread: {} got token: {}", id, token);
ch.send(token - 1);
if token <= n_tasks {
return;
#[feature(managed_boxes)];
-extern crate extra;
-
use std::io;
use std::io::stdio::StdReader;
use std::io::BufferedReader;
fn run(repeat: int, depth: int) {
for _ in range(0, repeat) {
- info!("starting {:.4f}", precise_time_s());
+ println!("starting {:.4f}", precise_time_s());
task::try(proc() {
recurse_or_fail(depth, None)
});
- info!("stopping {:.4f}", precise_time_s());
+ println!("stopping {:.4f}", precise_time_s());
}
}
fn recurse_or_fail(depth: int, st: Option<State>) {
if depth == 0 {
- info!("unwinding {:.4f}", precise_time_s());
+ println!("unwinding {:.4f}", precise_time_s());
fail!();
} else {
let depth = depth - 1;
let (sum_port, sum_chan) = stream::<int>();
start_chan.send(sum_chan);
let sum = sum_port.recv();
- error!("How many tasks? {} tasks.", sum);
+ println!("How many tasks? {} tasks.", sum);
}
// ignore-fast #[feature] doesn't work with check-fast
#[feature(asm)];
-fn foo(x: int) { info!("{}", x); }
+fn foo(x: int) { println!("{}", x); }
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-fast #[feature] doesn't work with check-fast
+#[feature(asm)];
+
+#[allow(dead_code)];
+
+#[cfg(target_arch = "x86")]
+#[cfg(target_arch = "x86_64")]
+pub fn main() {
+ // assignment not dead
+ let mut x: int = 0;
+ unsafe {
+ // extra colon
+ asm!("mov $1, $0" : "=r"(x) : "r"(5u), "0"(x) : : "cc");
+ //~^ WARNING unrecognized option
+ }
+ assert_eq!(x, 5);
+
+ unsafe {
+ // comma in place of a colon
+ asm!("add $2, $1; mov $1, $0" : "=r"(x) : "r"(x), "r"(8u) : "cc", "volatile");
+ //~^ WARNING expected a clobber, but found an option
+ }
+ assert_eq!(x, 13);
+}
+
+// #[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"))]
+// pub fn main() {}
+
+// At least one error is needed so that compilation fails
+#[static_assert]
+static b: bool = false; //~ ERROR static assertion failed
// ignore-fast #[feature] doesn't work with check-fast
#[feature(asm)];
-fn foo(x: int) { info!("{}", x); }
+fn foo(x: int) { println!("{}", x); }
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
// ignore-fast #[feature] doesn't work with check-fast
#[feature(asm)];
-fn foo(x: int) { info!("{}", x); }
+fn foo(x: int) { println!("{}", x); }
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
// ignore-fast #[feature] doesn't work with check-fast
#[feature(asm)];
-fn foo(x: int) { info!("{}", x); }
+fn foo(x: int) { println!("{}", x); }
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
fn test() {
let v: int;
v = 1; //~ NOTE prior assignment occurs here
- info!("v={}", v);
+ println!("v={}", v);
v = 2; //~ ERROR re-assignment of immutable variable
- info!("v={}", v);
+ println!("v={}", v);
}
fn main() {
fn main() {
let nyan : cat = cat(52u, 99);
- nyan.speak = || info!("meow"); //~ ERROR attempted to take value of method
+ nyan.speak = || println!("meow"); //~ ERROR attempted to take value of method
}
fn main() {
#[attr] //~ ERROR expected item after attributes
- info!("hi");
+ println!("hi");
}
let a: clam = clam{x: @1, y: @2};
let b: clam = clam{x: @10, y: @20};
let z: int = a.x + b.y; //~ ERROR binary operation `+` cannot be applied to type `@int`
- info!("{:?}", z);
+ println!("{:?}", z);
assert_eq!(z, 21);
let forty: fish = fish{a: @40};
let two: fish = fish{a: @2};
let answer: int = forty.a + two.a;
//~^ ERROR binary operation `+` cannot be applied to type `@int`
- info!("{:?}", answer);
+ println!("{:?}", answer);
assert_eq!(answer, 42);
}
// error-pattern:expected `~str` but found `int`
static i: ~str = 10i;
-fn main() { info!("{:?}", i); }
+fn main() { println!("{:?}", i); }
impl Drop for X {
fn drop(&mut self) {
- error!("destructor runs");
+ println!("destructor runs");
}
}
impl Drop for X {
fn drop(&mut self) {
- error!("destructor runs");
+ println!("destructor runs");
}
}
impl Drop for X {
fn drop(&mut self) {
- error!("destructor runs");
+ println!("destructor runs");
}
}
impl Drop for X {
fn drop(&mut self) {
- error!("destructor runs");
+ println!("destructor runs");
}
}
impl Drop for X {
fn drop(&mut self) {
- error!("destructor runs");
+ println!("destructor runs");
}
}
fn main() {
let i = 8;
- let f = coerce(|| error!("{:?}", i) );
+ let f = coerce(|| println!("{:?}", i) );
f();
}
fn main() {
let red: color = rgb(255, 0, 0);
match red {
- rgb(r, g, b) => { info!("rgb"); }
- hsl(h, s, l) => { info!("hsl"); }
+ rgb(r, g, b) => { println!("rgb"); }
+ hsl(h, s, l) => { println!("hsl"); }
}
}
fn main() {
let i: int;
- info!("{}", false && { i = 5; true });
- info!("{}", i); //~ ERROR use of possibly uninitialized variable: `i`
+ println!("{}", false && { i = 5; true });
+ println!("{}", i); //~ ERROR use of possibly uninitialized variable: `i`
}
p[0] = 5; //~ ERROR cannot assign
- info!("{}", *q);
+ println!("{}", *q);
}
fn borrow(_x: &[int], _f: ||) {}
fn main() {
let x: int;
force(|| { //~ ERROR capture of possibly uninitialized variable: `x`
- info!("{}", x);
+ println!("{}", x);
});
}
impl<'a> Drop for defer<'a> {
fn drop(&mut self) {
unsafe {
- error!("{:?}", self.x);
+ println!("{:?}", self.x);
}
}
}
x = 0;
}
- info!("{}", x); //~ ERROR use of possibly uninitialized variable: `x`
+ println!("{}", x); //~ ERROR use of possibly uninitialized variable: `x`
return 17;
}
-fn main() { info!("{}", foo()); }
+fn main() { println!("{}", foo()); }
x = 0;
}
- info!("{}", x); //~ ERROR use of possibly uninitialized variable: `x`
+ println!("{}", x); //~ ERROR use of possibly uninitialized variable: `x`
return 17;
}
-fn main() { info!("{}", foo()); }
+fn main() { println!("{}", foo()); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn foo(x: int) { info!("{}", x); }
+fn foo(x: int) { println!("{}", x); }
fn main() {
let x: int; if 1 > 2 { x = 10; }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn foo(x: int) { info!("{:?}", x); }
+fn foo(x: int) { println!("{:?}", x); }
fn main() {
let x: int;
if 1 > 2 {
- info!("whoops");
+ println!("whoops");
} else {
x = 10;
}
let i: int;
i //~ ERROR use of possibly uninitialized variable: `i`
};
- error!("{:?}", f());
+ println!("{:?}", f());
}
let v = ~3;
let _w = &v;
task::spawn(proc() {
- info!("v={}", *v);
+ println!("v={}", *v);
//~^ ERROR cannot move `v` into closure
});
}
let v = ~3;
let _w = &v;
task::spawn(proc() {
- info!("v={}", *v);
+ println!("v={}", *v);
//~^ ERROR cannot move
});
}
}
}
let z = tail[0].clone();
- info!("{:?}", z);
+ println!("{:?}", z);
}
_ => {
unreachable!();
let x: int = 3;
let y: &mut int = &mut x; //~ ERROR cannot borrow
*y = 5;
- info!("{:?}", *y);
+ println!("{:?}", *y);
}
fn main() {
let i: int;
- info!("{}", false || { i = 5; true });
- info!("{}", i); //~ ERROR use of possibly uninitialized variable: `i`
+ println!("{}", false || { i = 5; true });
+ println!("{}", i); //~ ERROR use of possibly uninitialized variable: `i`
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn foo(x: int) { info!("{}", x); }
+fn foo(x: int) { println!("{}", x); }
fn main() {
let x: int;
v = 3;
break;
}
- info!("{}", v); //~ ERROR use of possibly uninitialized variable: `v`
+ println!("{}", v); //~ ERROR use of possibly uninitialized variable: `v`
}
fn main() {
impl cat {
pub fn eat(&self) -> bool {
if self.how_hungry > 0 {
- error!("OM NOM NOM");
+ println!("OM NOM NOM");
self.how_hungry -= 2;
return true;
}
else {
- error!("Not hungry!");
+ println!("Not hungry!");
return false;
}
}
impl cat {
fn meow(&self) {
- error!("Meow");
+ println!("Meow");
self.meows += 1;
if self.meows % 5 == 0 {
self.how_hungry += 1;
impl cat {
fn sleep(&self) { loop{} }
fn meow(&self) {
- error!("Meow");
+ println!("Meow");
meows += 1u; //~ ERROR unresolved name
sleep(); //~ ERROR unresolved name
}
let x = foo(10);
let _y = x.clone();
//~^ ERROR does not implement any method in scope
- error!("{:?}", x);
+ println!("{:?}", x);
}
fn main() {
return;
- info!("Paul is dead");
+ println!("Paul is dead");
}
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
#[deriving(Eq)]
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
#[deriving(Eq)]
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
#[deriving(Eq)]
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
#[deriving(Eq)]
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
#[deriving(Eq)]
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
#[deriving(Eq)]
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
#[deriving(Eq)]
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
#[deriving(Eq)]
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
#[deriving(Eq, Ord, TotalEq)]
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
#[deriving(Eq, Ord, TotalEq)]
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
#[deriving(Eq, Ord, TotalEq)]
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
#[deriving(Eq, Ord, TotalEq)]
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
// This file was auto-generated using 'src/etc/generate-keyword-span-tests.py'
#[feature(struct_variant)];
-extern crate extra;
extern crate rand;
impl Drop for X {
fn drop(&mut self) {
- error!("value: {}", self.x);
+ println!("value: {}", self.x);
}
}
fn main() {
let x = X { x: ~"hello" };
let y = unwrap(x);
- error!("contents: {}", y);
+ println!("contents: {}", y);
}
impl Drop for X {
fn drop(&mut self) {
- error!("value: {}", self.x);
+ println!("value: {}", self.x);
}
}
let x = X { x: ~"hello" };
match x {
- X { x: y } => error!("contents: {}", y)
+ X { x: y } => println!("contents: {}", y)
//~^ ERROR cannot move out of type `X`, which defines the `Drop` trait
}
}
// except according to those terms.
// error-pattern: unresolved name `this_does_nothing_what_the`.
-fn main() { info!("doing"); this_does_nothing_what_the; info!("boing"); }
+fn main() { println!("doing"); this_does_nothing_what_the; println!("boing"); }
}
mod bar {
- fn x() { info!("x"); }
+ fn x() { println!("x"); }
pub fn y() { }
}
fn main() {
let a = if true { true };
- info!("{:?}", a);
+ println!("{:?}", a);
}
use module_of_many_things::*;
mod module_of_many_things {
- pub fn f1() { info!("f1"); }
- pub fn f2() { info!("f2"); }
- fn f3() { info!("f3"); }
- pub fn f4() { info!("f4"); }
+ pub fn f1() { println!("f1"); }
+ pub fn f2() { println!("f2"); }
+ fn f3() { println!("f3"); }
+ pub fn f4() { println!("f4"); }
}
mod circ1 {
pub use circ2::f2;
- pub fn f1() { info!("f1"); }
+ pub fn f1() { println!("f1"); }
pub fn common() -> uint { return 0u; }
}
mod circ2 {
pub use circ1::f1;
- pub fn f2() { info!("f2"); }
+ pub fn f2() { println!("f2"); }
pub fn common() -> uint { return 1u; }
}
use zed::bar;
use zed::baz;
mod zed {
- pub fn bar() { info!("bar"); }
+ pub fn bar() { println!("bar"); }
}
fn main(args: ~[str]) { bar(); }
mod baz {}
mod zed {
- pub fn bar() { info!("bar3"); }
+ pub fn bar() { println!("bar3"); }
}
fn main(args: ~[str]) { bar(); }
// error-pattern: unresolved
use main::bar;
-fn main(args: ~[str]) { info!("foo"); }
+fn main(args: ~[str]) { println!("foo"); }
mod a { pub use b::foo; }
mod b { pub use a::foo; }
-fn main(args: ~[str]) { info!("loop"); }
+fn main(args: ~[str]) { println!("loop"); }
fn foo(a: uint) -> uint { a }
fn main() {
- info!("{:u}", foo(10i)); //~ ERROR mismatched types
+ println!("{:u}", foo(10i)); //~ ERROR mismatched types
}
// except according to those terms.
fn main() {
- error!("{:?}", x); //~ ERROR unresolved name `x`.
+ println!("{:?}", x); //~ ERROR unresolved name `x`.
}
#[deny(unreachable_code)];
#[allow(unused_variable)];
#[allow(dead_code)];
+#[allow(deprecated_owned_vector)];
fn fail_len(v: ~[int]) -> uint {
let mut i = 3;
// error-pattern: unresolved name `foobar`.
-fn main(args: ~[str]) { info!("{:?}", foobar); }
+fn main(args: ~[str]) { println!("{:?}", foobar); }
impl Drop for C {
fn drop(&mut self) {
- error!("dropping: {:?}", self.x);
+ println!("dropping: {:?}", self.x);
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
fn siphash(k0 : u64) {
struct siphash {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
fn siphash<T>() {
trait t {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
trait siphash {
fn result(&self) -> u64;
fn reset(&self);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
trait SipHash {
fn reset(&self);
}
{
let _z = match g(1, 2) {
- g(x, x) => { info!("{:?}", x + x); }
+ g(x, x) => { println!("{:?}", x + x); }
//~^ ERROR identifier `x` is bound more than once in the same pattern
};
let _z = match i(l(1, 2), m(3, 4)) {
i(l(x, _), m(_, x)) //~ ERROR identifier `x` is bound more than once in the same pattern
- => { error!("{:?}", x + x); }
+ => { println!("{:?}", x + x); }
};
let _z = match (1, 2) {
}
fn main() {
- info!("Result: ");
+ println!("Result: ");
}
static y: int = foo + 1; //~ ERROR: attempt to use a non-constant value in a constant
- error!("{}", y);
+ println!("{}", y);
}
Bar = foo //~ ERROR attempt to use a non-constant value in a constant
}
- error!("{:?}", Bar);
+ println!("{:?}", Bar);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#[allow(deprecated_owned_vector)];
// Verify the compiler fails with an error on infinite function
// recursions.
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[deny(deprecated_owned_vector)];
+
+fn main() {
+ ~[1]; //~ ERROR use of deprecated `~[]`
+ //~^ ERROR use of deprecated `~[]`
+ std::vec::with_capacity::<int>(10); //~ ERROR use of deprecated `~[]`
+}
#[feature(managed_boxes)];
#[forbid(heap_memory)];
#[allow(dead_code)];
+#[allow(deprecated_owned_vector)];
struct Foo {
x: @int //~ ERROR type uses managed
#[feature(globs)];
#[deny(unused_imports)];
#[allow(dead_code)];
+#[allow(deprecated_owned_vector)];
use cal = bar::c::cc;
#[allow(dead_assignment)];
#[allow(unused_variable)];
#[allow(dead_code)];
+#[allow(deprecated_owned_vector)];
#[deny(unused_mut)];
fn main() {
#[allow(dead_code)];
#[deny(unused_unsafe)];
+#[allow(deprecated_owned_vector)];
mod foo {
extern {
// Tests that a function with a ! annotation always actually fails
// error-pattern: some control paths may return
-fn bad_bang(i: uint) -> ! { info!("{}", 3); }
+fn bad_bang(i: uint) -> ! { println!("{}", 3); }
fn main() { bad_bang(5u); }
// except according to those terms.
fn force(f: || -> int) -> int { f() }
-fn main() { info!("{:?}", force(|| {})); } //~ ERROR mismatched types
+fn main() { println!("{:?}", force(|| {})); } //~ ERROR mismatched types
let y: ~int = ~42;
let mut x: ~int;
loop {
- info!("{:?}", y);
+ println!("{:?}", y);
loop {
loop {
loop {
let y: ~int = ~42;
let mut x: ~int;
loop {
- info!("{:?}", y); //~ ERROR use of moved value: `y`
+ println!("{:?}", y); //~ ERROR use of moved value: `y`
while true { while true { while true { x = y; x.clone(); } } }
//~^ ERROR use of moved value: `y`
}
fn main() {
let x = ~5;
let y = x;
- info!("{:?}", *x); //~ ERROR use of moved value: `x`
+ println!("{:?}", *x); //~ ERROR use of moved value: `x`
y.clone();
}
// except according to those terms.
fn send<T:Send>(ch: _chan<T>, data: T) {
- info!("{:?}", ch);
- info!("{:?}", data);
+ println!("{:?}", ch);
+ println!("{:?}", data);
fail!();
}
// message after the send deinitializes it
fn test00_start(ch: _chan<~int>, message: ~int, _count: ~int) {
send(ch, message);
- info!("{:?}", message); //~ ERROR use of moved value: `message`
+ println!("{:?}", message); //~ ERROR use of moved value: `message`
}
fn main() { fail!(); }
fn main() {
match true { false => { my_fail(); } true => { } }
- info!("{:?}", x); //~ ERROR unresolved name `x`.
+ println!("{:?}", x); //~ ERROR unresolved name `x`.
let x: int;
}
// temporary kinds wound up being stored in a cache and used later.
// See middle::ty::type_contents() for more information.
-extern crate extra;
-
struct List { key: int, next: Option<~List> }
fn foo(node: ~List) -> int {
assert_eq!((arc_v.get())[2], 3);
- info!("{:?}", arc_v);
+ println!("{:?}", arc_v);
}
assert_eq!((arc_v.get())[2], 3); //~ ERROR use of moved value: `arc_v`
- info!("{:?}", arc_v); //~ ERROR use of moved value: `arc_v`
+ println!("{:?}", arc_v); //~ ERROR use of moved value: `arc_v`
}
task::spawn(proc() {
let y = x; //~ ERROR does not fulfill `Send`
- error!("{:?}", y);
+ println!("{:?}", y);
});
}
fn main() {
let x = foo(10);
let _y = x.clone(); //~ ERROR does not implement any method in scope
- error!("{:?}", x);
+ println!("{:?}", x);
}
}
fn main() {
- info!("{:?}", foo{ x: 1 } as int);
+ println!("{:?}", foo{ x: 1 } as int);
}
// compile-flags: -D type-overflow
-fn main() { info!("{}", 300u8); } //~ error: literal out of range for its type
+fn main() { println!("{}", 300u8); } //~ error: literal out of range for its type
let foo = Foo { bar: [1u8, 2, 3, 4, 5], baz: 10i32 };
unsafe {
let oof: Oof<[u8, .. 5], i32> = cast::transmute(foo);
- info!("{:?}", oof);
+ println!("{:?}", oof);
}
}
let foo = Foo { bar: 1, baz: 10 };
unsafe {
let oof: Oof = cast::transmute(foo);
- info!("{:?}", oof);
+ println!("{:?}", oof);
}
}
// except according to those terms.
-extern crate extra;
-
enum bar { t1((), Option<~[int]>), t2, }
// n.b. my change changes this error message, but I think it's right -- tjc
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
// error-pattern: mismatched types
enum bar { t1((), Option<~[int]>), t2, }
fn foo(t: bar) {
match t {
t1(_, Some::<int>(x)) => {
- info!("{:?}", x);
+ println!("{:?}", x);
}
_ => { fail!(); }
}
// Can't do this copy
let x = ~~~A {y: r(i)};
let _z = x.clone(); //~ ERROR failed to find an implementation
- info!("{:?}", x);
+ println!("{:?}", x);
}
- error!("{:?}", *i);
+ println!("{:?}", *i);
}
#[feature(quote)];
-extern crate extra;
extern crate syntax;
use io::*;
#[feature(quote)];
-extern crate extra;
extern crate syntax;
-use extra::io::*;
-
use syntax::diagnostic;
use syntax::ast;
use syntax::codemap;
fn main() {
let mut d = dog();
d.chase_cat();
- info!("cats_chased: {}", d.cats_chased);
+ println!("cats_chased: {}", d.cats_chased);
}
fn main() {
let i = 3;
wants_static_fn(|| { //~ ERROR cannot infer
- info!("i={}", i);
+ println!("i={}", i);
})
}
// except according to those terms.
mod argparse {
- extern crate extra;
-
pub struct Flag<'a> {
name: &'a str,
desc: &'a str,
fn main() {
let x = return_it();
- info!("foo={}", *x);
+ println!("foo={}", *x);
}
fn main() {
let x = return_it();
- info!("foo={}", *x);
+ println!("foo={}", *x);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
fn main() {
trait seq { }
// error-pattern: mismatched types
-extern crate extra;
-
use std::task;
fn main() { task::spawn(|| -> int { 10 }); }
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test checks that it is not possible to enable global type
+// inference by using the `_` type placeholder.
+
+fn test() -> _ { 5 }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+fn test2() -> (_, _) { (5u, 5u) }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+static TEST3: _ = "test";
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+static TEST4: _ = 145u16;
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+static TEST5: (_, _) = (1, 2);
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+//~^^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+fn test6(_: _) { }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+fn test7(x: _) { let _x: uint = x; }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+fn test8(_f: fn() -> _) { }
+//~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+struct Test9;
+
+impl Test9 {
+ fn test9(&self) -> _ { () }
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+ fn test10(&self, _x : _) { }
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+}
+
+impl Clone for Test9 {
+ fn clone(&self) -> _ { Test9 }
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+ fn clone_from(&mut self, other: _) { *self = Test9; }
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+}
+
+struct Test10 {
+ a: _,
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+ b: (_, _),
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+ //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+}
+
+pub fn main() {
+ fn fn_test() -> _ { 5 }
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+ fn fn_test2() -> (_, _) { (5u, 5u) }
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+ //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+ static FN_TEST3: _ = "test";
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+ static FN_TEST4: _ = 145u16;
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+ static FN_TEST5: (_, _) = (1, 2);
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+ //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+ fn fn_test6(_: _) { }
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+ fn fn_test7(x: _) { let _x: uint = x; }
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+ fn fn_test8(_f: fn() -> _) { }
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+ struct FnTest9;
+
+ impl FnTest9 {
+ fn fn_test9(&self) -> _ { () }
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+ fn fn_test10(&self, _x : _) { }
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+ }
+
+ impl Clone for FnTest9 {
+ fn clone(&self) -> _ { FnTest9 }
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+
+ fn clone_from(&mut self, other: _) { *self = FnTest9; }
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+ }
+
+ struct FnTest10 {
+ a: _,
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+ b: (_, _),
+ //~^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+ //~^^ ERROR the type placeholder `_` is not allowed within types on item signatures.
+ }
+
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test checks that the `_` type placeholder does not react
+// badly if put as a lifetime parameter.
+
+struct Foo<'a, T> {
+ r: &'a T
+}
+
+pub fn main() {
+ let c: Foo<_, _> = Foo { r: &5u };
+ //~^ ERROR wrong number of type arguments: expected 1 but found 2
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test checks that the `_` type placeholder does not react
+// badly if put as a lifetime parameter.
+
+struct Foo<'a, T> {
+ r: &'a T
+}
+
+pub fn main() {
+ let c: Foo<_, uint> = Foo { r: &5 };
+ //~^ ERROR wrong number of type arguments: expected 1 but found 2
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test checks that genuine type errors with partial
+// type hints are understandable.
+
+struct Foo<T>;
+struct Bar<U>;
+
+pub fn main() {
+}
+
+fn test1() {
+ let x: Foo<_> = Bar::<uint>;
+ //~^ ERROR mismatched types: expected `Foo<<generic #0>>` but found `Bar<uint>`
+ let y: Foo<uint> = x;
+}
+
+fn test2() {
+ let x: Foo<_> = Bar::<uint>;
+ //~^ ERROR mismatched types: expected `Foo<<generic #0>>` but found `Bar<uint>`
+ //~^^ ERROR cannot determine a type for this local variable: unconstrained type
+}
fn main() {
let i = ~r { b: true };
let _j = i.clone(); //~ ERROR failed to find an implementation
- info!("{:?}", i);
+ println!("{:?}", i);
}
let r2 = ~[~r { i: i2 }];
f(r1.clone(), r2.clone());
//~^ ERROR failed to find an implementation of
- info!("{:?}", (r2, i1.get()));
- info!("{:?}", (r1, i2.get()));
+ println!("{:?}", (r2, i1.get()));
+ println!("{:?}", (r1, i2.get()));
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-use extra; //~ ERROR unresolved import (maybe you meant `extra::*`?)
+extern crate collections;
+use collections; //~ ERROR unresolved import (maybe you meant `collections::*`?)
fn main() {}
use std::libc;
fn main() {
- info!("{:?}", 1.0 as *libc::FILE); // Can't cast float to foreign.
+ println!("{:?}", 1.0 as *libc::FILE); // Can't cast float to foreign.
}
fn f() {
let v = ~[1i];
- info!("{}", v.some_field_name); //type error
+ println!("{}", v.some_field_name); //type error
}
fn main() { }
let i = ~[r(0)];
let j = ~[r(1)];
let k = i + j;
- info!("{}", j);
+ println!("{}", j);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
+extern crate test;
fn f() {
}
-use extra::net; //~ ERROR `use` and `extern crate` declarations must precede items
+use test::net; //~ ERROR `use` and `extern crate` declarations must precede items
fn main() {
}
// Make sure functions have proper names
// debugger:info functions
-// check:static void [...]main();
-// check:static void [...]some_function();
-// check:static void [...]some_other_function();
-// check:static void [...]zzz();
+// check:[...]void[...]main([...]);
+// check:[...]void[...]some_function([...]);
+// check:[...]void[...]some_other_function([...]);
+// check:[...]void[...]zzz([...]);
// debugger:rbreak zzz
// debugger:run
// except according to those terms.
// error-pattern:quux
-fn my_err(s: ~str) -> ! { error!("{}", s); fail!("quux"); }
+fn my_err(s: ~str) -> ! { println!("{}", s); fail!("quux"); }
fn main() { 3u == my_err(~"bye"); }
// except according to those terms.
// error-pattern:quux
-fn my_err(s: ~str) -> ! { error!("{}", s); fail!("quux"); }
+fn my_err(s: ~str) -> ! { println!("{}", s); fail!("quux"); }
fn main() { 3u == my_err(~"bye"); }
// wrap around to a small number.
let idx = uint::MAX & !(uint::MAX >> 1u);
- error!("ov2 idx = 0x%x", idx);
+ println!("ov2 idx = 0x%x", idx);
// This should fail.
- error!("ov2 0x%x", x[idx]);
+ println!("ov2 0x%x", x[idx]);
}
// This test is only meaningful on 32-bit hosts.
let idx = u64::MAX & !(u64::MAX >> 1u);
- error!("ov3 idx = 0x%8.8x%8.8x",
+ println!("ov3 idx = 0x%8.8x%8.8x",
(idx >> 32) as uint,
idx as uint);
// This should fail.
- error!("ov3 0x%x", x[idx]);
+ println!("ov3 0x%x", x[idx]);
}
#[cfg(target_arch="x86_64")]
fn main() {
// This version just fails anyways, for symmetry on 64-bit hosts.
let x = ~[1u,2u,3u];
- error!("ov3 0x%x", x[200]);
+ println!("ov3 0x%x", x[200]);
}
let base = x.as_ptr() as uint;
let idx = base / mem::size_of::<uint>();
- error!("ov1 base = 0x{:x}", base);
- error!("ov1 idx = 0x{:x}", idx);
- error!("ov1 sizeof::<uint>() = 0x{:x}", mem::size_of::<uint>());
- error!("ov1 idx * sizeof::<uint>() = 0x{:x}",
+ println!("ov1 base = 0x{:x}", base);
+ println!("ov1 idx = 0x{:x}", idx);
+ println!("ov1 sizeof::<uint>() = 0x{:x}", mem::size_of::<uint>());
+ println!("ov1 idx * sizeof::<uint>() = 0x{:x}",
idx * mem::size_of::<uint>());
// This should fail.
- error!("ov1 0x{:x}", x[idx]);
+ println!("ov1 0x{:x}", x[idx]);
}
for _ in range(0, 10u) {
task::spawn(proc() {
let result = count(5u);
- info!("result = %?", result);
+ println!("result = %?", result);
fail!();
});
}
// except according to those terms.
// error-pattern:woe
-fn f(a: int) { info!("{}", a); }
+fn f(a: int) { println!("{}", a); }
fn main() { f(fail!("woe")); }
// except according to those terms.
// error-pattern:moop
-extern crate extra;
fn main() { fail!("moop"); }
// except according to those terms.
// error-pattern:meh
-extern crate extra;
fn main() { let str_var: ~str = ~"meh"; fail!("{}", str_var); }
// except according to those terms.
// error-pattern:moop
-extern crate extra;
fn main() { for _ in range(0u, 10u) { fail!("moop"); } }
fn foo(x: uint) {
if even(x) {
- info!("{}", x);
+ println!("{}", x);
} else {
fail!("Number is odd");
}
// except according to those terms.
// error-pattern:quux
-fn my_err(s: ~str) -> ! { error!("{}", s); fail!("quux"); }
+fn my_err(s: ~str) -> ! { println!("{}", s); fail!("quux"); }
fn main() { if my_err(~"bye") { } }
}
}
-fn main() { error!("{}", cmp()); }
+fn main() { println!("{}", cmp()); }
// See the hack in upcall_call_shim_on_c_stack where it messes
// with the stack limit.
-extern crate extra;
-
use std::libc;
use std::task;
// Just testing unwinding
-extern crate extra;
-
use std::task;
fn getbig_and_fail(i: int) {
// Just testing unwinding
-extern crate extra;
-
use std::task;
fn getbig_and_fail(i: int) {
use std::result;
fn main() {
- error!("{:?}", result::Err::<int,~str>(~"kitty").unwrap());
+ println!("{:?}", result::Err::<int,~str>(~"kitty").unwrap());
}
// error-pattern:whatever
+#[feature(phase)];
+#[phase(syntax, link)] extern crate log;
use std::os;
fn main() {
// error-pattern:whatever
+#[feature(phase)];
+#[phase(syntax, link)] extern crate log;
use std::os;
use std::task;
// error-pattern:whatever
+#[feature(phase)];
+#[phase(syntax, link)] extern crate log;
use std::os;
fn main() {
// compile-flags:--test
// check-stdout
-extern crate extra;
-
mod m {
pub fn exported() { }
// during unwinding
fn recurse() {
- info!("don't optimize me out");
+ println!("don't optimize me out");
recurse();
}
fn main() {
let y = ~0;
let x: @proc() = @(proc() {
- error!("{:?}", y.clone());
+ println!("{:?}", y.clone());
});
failfn();
- error!("{:?}", x);
+ println!("{:?}", x);
}
cast::forget(i1);
let x = @r(i1p);
failfn();
- error!("{:?}", x);
+ println!("{:?}", x);
}
}
fn main() {
let x = @~"hi";
failfn();
- error!("{:?}", x);
+ println!("{:?}", x);
}
fn main() {
let x = @~~0;
failfn();
- error!("{:?}", x);
+ println!("{:?}", x);
}
fn main() {
let x = @~0;
failfn();
- error!("{:?}", x);
+ println!("{:?}", x);
}
fn main() {
let x = @~[0, 1, 2, 3, 4, 5];
failfn();
- error!("{:?}", x);
+ println!("{:?}", x);
}
#[crate_id="boot#0.1"];
#[crate_type="dylib"];
#[no_uv];
+#[feature(phase)];
extern crate rustuv;
extern crate green;
+#[phase(syntax, link)] extern crate log;
use std::rt::crate_map::{CrateMap, rust_set_crate_map};
#[no_mangle] // this needs to get called from C
pub extern "C" fn foo(argc: int, argv: **u8) -> int {
green::start(argc, argv, proc() {
- if log_enabled!(std::logging::DEBUG) { return }
+ if log_enabled!(log::DEBUG) { return }
fail!()
})
}
#[feature(quote)];
-extern crate extra;
extern crate syntax;
use std::io::*;
});
stdout().write_line(s);
if expect != ~"" {
- error!("expect: '%s', got: '%s'", expect, s);
+ println!("expect: '%s', got: '%s'", expect, s);
assert_eq!(s, expect);
}
}
pub fn main() {
let (a, b) = f(22_u64, 44u16).f();
- info!("a={:?} b={:?}", a, b);
+ println!("a={:?} b={:?}", a, b);
assert_eq!(a, 22u64);
assert_eq!(b, 44u16);
}
pub fn main() {
let a: int = 10;
- info!("{}", a);
+ println!("{}", a);
assert_eq!(a * (a - 1), 90);
}
assert_eq!(i32_b << 1, i32_b << 1);
assert_eq!(i32_b >> 1, i32_b >> 1);
assert_eq!(i32_b & i32_b << 1, 0);
- info!("{}", i32_b | i32_b << 1);
+ println!("{}", i32_b | i32_b << 1);
assert_eq!(i32_b | i32_b << 1, 0x30303030);
}
--- /dev/null
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-fast #[feature] doesn't work with check-fast
+#[feature(asm)];
+
+#[cfg(target_arch = "x86")]
+#[cfg(target_arch = "x86_64")]
+unsafe fn next_power_of_2(n: u32) -> u32 {
+ let mut tmp = n;
+ asm!("dec $0" : "+rm"(tmp) :: "cc");
+ let mut shift = 1u;
+ while shift <= 16 {
+ asm!(
+ "shr %cl, $2
+ or $2, $0
+ shl $$1, $1"
+ : "+&rm"(tmp), "+{ecx}"(shift) : "r"(tmp) : "cc"
+ );
+ }
+ asm!("inc $0" : "+rm"(tmp) :: "cc");
+ return tmp;
+}
+
+#[cfg(target_arch = "x86")]
+#[cfg(target_arch = "x86_64")]
+pub fn main() {
+ unsafe {
+ assert_eq!(64, next_power_of_2(37));
+ assert_eq!(2147483648, next_power_of_2(2147483647));
+ }
+
+ let mut y: int = 5;
+ let x: int;
+ unsafe {
+ // Treat the output as initialization.
+ asm!(
+ "shl $2, $1
+ add $3, $1
+ mov $1, $0"
+ : "=r"(x), "+r"(y) : "i"(3u), "ir"(7u) : "cc"
+ );
+ }
+ assert_eq!(x, 47);
+ assert_eq!(y, 47);
+
+ let mut x = x + 1;
+ assert_eq!(x, 48);
+
+ unsafe {
+ // Assignment to mutable.
+ // Early clobber "&":
+ // Forbids the use of a single register by both operands.
+ asm!("shr $$2, $1; add $1, $0" : "+&r"(x) : "r"(x) : "cc");
+ }
+ assert_eq!(x, 60);
+}
+
+#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"))]
+pub fn main() {}
// error-pattern:expected item
#[foo = "bar"]
-extern crate extra;
+extern crate test;
pub fn main() {
}
mod m {
#[foo = "bar"]
- extern crate extra;
+ extern crate test;
}
pub fn main() {
fn f<T,U>(x: T, y: U) -> Pair<T, U> { return Pair {a: x, b: y}; }
pub fn main() {
- info!("{:?}", f(Triple {x: 3, y: 4, z: 5}, 4).a.x);
- info!("{:?}", f(5, 6).a);
+ println!("{:?}", f(Triple {x: 3, y: 4, z: 5}, 4).a.x);
+ println!("{:?}", f(5, 6).a);
}
fn runtest(me: &str) {
let mut env = os::env();
- match env.iter().position(|&(ref s, _)| "RUST_LOG" == *s) {
+ match env.iter().position(|&(ref s, _)| "RUST_BACKTRACE" == *s) {
Some(i) => { env.remove(i); }
None => {}
}
- env.push((~"RUST_LOG", ~"std::rt::backtrace"));
+ env.push((~"RUST_BACKTRACE", ~"1"));
// Make sure that the stack trace is printed
let mut p = Process::configure(ProcessConfig {
let mut r = p(1, 2);
unsafe {
- error!("q = {:x}, r = {:x}",
+ println!("q = {:x}, r = {:x}",
(::std::cast::transmute::<*p, uint>(&q)),
(::std::cast::transmute::<*p, uint>(&r)));
}
a ^= b;
b ^= a;
a = a ^ b;
- info!("{}", a);
- info!("{}", b);
+ println!("{}", a);
+ println!("{}", b);
assert_eq!(b, 1);
assert_eq!(a, 2);
assert_eq!(!0xf0 & 0xff, 0xf);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
fn asSendfn(f: proc() -> uint) -> uint {
return f();
}
// Statement form does not require parentheses:
for i in v.iter() {
- info!("{:?}", *i);
+ println!("{:?}", *i);
}
}
pub fn main() {
fn as_buf<T>(s: ~str, f: |~str| -> T) -> T { f(s) }
- as_buf(~"foo", |foo: ~str| -> () error!("{}", foo) );
+ as_buf(~"foo", |foo: ~str| -> () println!("{}", foo) );
}
odds += 1;
}
});
- error!("{:?}", odds);
+ println!("{:?}", odds);
assert_eq!(odds, 4);
}
sum += *i * *j;
});
});
- error!("{:?}", sum);
+ println!("{:?}", sum);
assert_eq!(sum, 225);
}
add_int(ints, 44);
iter_ints(ints, |i| {
- error!("int = {}", *i);
+ println!("int = {}", *i);
true
});
- error!("ints={:?}", ints);
+ println!("ints={:?}", ints);
}
assert_eq!(&(*x.f) as *int, &(*b_x) as *int);
x = @F {f: ~4};
- info!("&*b_x = {:p}", &(*b_x));
+ println!("&*b_x = {:p}", &(*b_x));
assert_eq!(*b_x, 3);
assert!(&(*x.f) as *int != &(*b_x) as *int);
})
assert_eq!(&(*x.f) as *int, &(*b_x) as *int);
*x = @F{f: ~4};
- info!("&*b_x = {:p}", &(*b_x));
+ println!("&*b_x = {:p}", &(*b_x));
assert_eq!(*b_x, 3);
assert!(&(*x.f) as *int != &(*b_x) as *int);
})
assert_eq!(&(*x) as *int, &(*b_x) as *int);
x = @22;
- info!("&*b_x = {:p}", &(*b_x));
+ println!("&*b_x = {:p}", &(*b_x));
assert_eq!(*b_x, 3);
assert!(&(*x) as *int != &(*b_x) as *int);
})
exp = 4;
}
- info!("*r = {}, exp = {}", *r, exp);
+ println!("*r = {}, exp = {}", *r, exp);
assert_eq!(*r, exp);
x = @5;
y = @6;
- info!("*r = {}, exp = {}", *r, exp);
+ println!("*r = {}, exp = {}", *r, exp);
assert_eq!(*r, exp);
assert_eq!(x, @5);
assert_eq!(y, @6);
assert_eq!(&(*x.f) as *int, &(*b_x) as *int);
x = @F {f: ~4};
- info!("&*b_x = {:p}", &(*b_x));
+ println!("&*b_x = {:p}", &(*b_x));
assert_eq!(*b_x, 3);
assert!(&(*x.f) as *int != &(*b_x) as *int);
})
fn length_is_even(_vs: @int) -> bool { return true; }
fn foo(_acc: int, n: int) {
- if is_odd(n) && length_is_even(some_box(1)) { error!("bloop"); }
+ if is_odd(n) && length_is_even(some_box(1)) { println!("bloop"); }
}
pub fn main() { foo(67, 5); }
fn length_is_even(_vs: @int) -> bool { return true; }
fn foo(_acc: int, n: int) {
- if is_odd(n) || length_is_even(some_box(1)) { error!("bloop"); }
+ if is_odd(n) || length_is_even(some_box(1)) { println!("bloop"); }
}
pub fn main() { foo(67, 5); }
pub fn main() {
let foo: int = 17;
let bfoo: Box<int> = Box {c: @foo};
- info!("see what's in our box");
+ println!("see what's in our box");
assert_eq!(unbox::<int>(bfoo), foo);
}
// ignore-android (FIXME #11419)
// exec-env:RUST_LOG=info
+#[feature(phase)];
+
#[no_uv];
extern crate native;
+#[phase(syntax, link)]
+extern crate log;
use std::fmt;
use std::io::{ChanReader, ChanWriter};
-use std::logging::{set_logger, Logger};
+use log::{set_logger, Logger};
struct MyWriter(ChanWriter);
pub fn main() {
let x = 3;
- info!("&x={:x}", (&x as *int as uint));
+ println!("&x={:x}", (&x as *int as uint));
}
pub fn main() {
let p = @22u;
let r = foo(p);
- info!("r={}", r);
+ println!("r={}", r);
assert_eq!(r, 22u);
}
pub fn main() {
//let bt0 = sys::frame_address();
- //info!("%?", bt0);
+ //println!("%?", bt0);
3u.to(10u, |i| {
println!("{}", i);
//let bt1 = sys::frame_address();
- //info!("%?", bt1);
+ //println!("%?", bt1);
//assert!(bt0 == bt1);
})
}
pub fn main() {
//let bt0 = sys::rusti::frame_address(1u32);
- //info!("%?", bt0);
+ //println!("%?", bt0);
cci_iter_lib::iter([1, 2, 3], |i| {
println!("{}", *i);
//assert!(bt0 == sys::rusti::frame_address(2u32));
// sys::frame_address() to determine if we are inlining is
// actually working.
//let bt0 = sys::frame_address();
- //info!("%?", bt0);
+ //println!("%?", bt0);
iter(~[1u, 2u, 3u], |i| {
println!("{}", i);
//let bt1 = sys::frame_address();
- //info!("%?", bt1);
+ //println!("%?", bt1);
//assert!(bt0 != bt1);
})
fn foo1() -> int { 1 }
// !fooA AND !bar
-#[cfg(not(fooA, bar))]
+#[cfg(not(fooA), not(bar))]
fn foo2() -> int { 2 }
// fooC OR (fooB AND !bar)
#[cfg(fooB, not(bar))]
fn foo2() -> int { 3 }
+// fooA AND bar
+#[cfg(fooA, bar)]
+fn foo3() -> int { 2 }
+
+// !(fooA AND bar)
+#[cfg(not(fooA, bar))]
+fn foo3() -> int { 3 }
pub fn main() {
assert_eq!(1, foo1());
assert_eq!(3, foo2());
+ assert_eq!(3, foo3());
}
impl Drop for cat {
#[cat_dropper]
- fn drop(&mut self) { error!("{} landed on hir feet" , self . name); }
+ fn drop(&mut self) { println!("{} landed on hir feet" , self . name); }
}
Actually, cats don't always land on their feet when you drop them.
*/
fn drop(&mut self) {
- error!("{} landed on hir feet", self.name);
+ println!("{} landed on hir feet", self.name);
}
}
fn print_out(thing: ~ToStr, expected: ~str) {
let actual = thing.to_str();
- info!("{}", actual);
+ println!("{}", actual);
assert_eq!(actual, expected);
}
impl dog {
fn bark(&mut self) -> int {
- info!("Woof {} {}", self.barks, self.volume);
+ println!("Woof {} {}", self.barks, self.volume);
self.barks += 1u;
if self.barks % 3u == 0u {
self.volume += 1;
if self.barks % 10u == 0u {
self.volume -= 2;
}
- info!("Grrr {} {}", self.barks, self.volume);
+ println!("Grrr {} {}", self.barks, self.volume);
self.volume
}
}
impl cat {
fn meow(&mut self) -> uint {
- info!("Meow");
+ println!("Meow");
self.meows += 1u;
if self.meows % 5u == 0u {
self.how_hungry += 1;
impl cat {
pub fn eat(&mut self) -> bool {
if self.how_hungry > 0 {
- error!("OM NOM NOM");
+ println!("OM NOM NOM");
self.how_hungry -= 2;
return true;
}
else {
- error!("Not hungry!");
+ println!("Not hungry!");
return false;
}
}
impl cat {
fn meow(&mut self) {
- error!("Meow");
+ println!("Meow");
self.meows += 1u;
if self.meows % 5u == 0u {
self.how_hungry += 1;
pub fn eat(&mut self) -> bool {
if self.how_hungry > 0 {
- error!("OM NOM NOM");
+ println!("OM NOM NOM");
self.how_hungry -= 2;
return true;
} else {
- error!("Not hungry!");
+ println!("Not hungry!");
return false;
}
}
impl<T> cat<T> {
fn meow(&mut self) {
self.meows += 1;
- error!("Meow {}", self.meows);
+ println!("Meow {}", self.meows);
if self.meows % 5 == 0 {
self.how_hungry += 1;
}
impl cat {
pub fn eat(&mut self) -> bool {
if self.how_hungry > 0 {
- error!("OM NOM NOM");
+ println!("OM NOM NOM");
self.how_hungry -= 2;
return true;
}
else {
- error!("Not hungry!");
+ println!("Not hungry!");
return false;
}
}
impl cat {
fn meow(&mut self) {
- error!("Meow");
+ println!("Meow");
self.meows += 1u;
if self.meows % 5u == 0u {
self.how_hungry += 1;
impl cat {
fn meow(&mut self) {
- error!("Meow");
+ println!("Meow");
self.meows += 1u;
if self.meows % 5u == 0u {
self.how_hungry += 1;
impl cat {
pub fn eat(&mut self) -> bool {
if self.how_hungry > 0 {
- error!("OM NOM NOM");
+ println!("OM NOM NOM");
self.how_hungry -= 2;
return true;
} else {
- error!("Not hungry!");
+ println!("Not hungry!");
return false;
}
}
pub fn eat(&mut self) -> bool {
if self.how_hungry > 0 {
- error!("OM NOM NOM");
+ println!("OM NOM NOM");
self.how_hungry -= 2;
return true;
}
else {
- error!("Not hungry!");
+ println!("Not hungry!");
return false;
}
}
impl cat {
fn meow(&mut self) {
- error!("Meow");
+ println!("Meow");
self.meows += 1u;
if self.meows % 5u == 0u {
self.how_hungry += 1;
fn print_out(thing: ~ToStr, expected: ~str) {
let actual = thing.to_str();
- info!("{}", actual);
+ println!("{}", actual);
assert_eq!(actual, expected);
}
pub fn eat(&mut self) -> bool {
if self.how_hungry > 0 {
- error!("OM NOM NOM");
+ println!("OM NOM NOM");
self.how_hungry -= 2;
return true;
} else {
- error!("Not hungry!");
+ println!("Not hungry!");
return false;
}
}
impl cat {
fn meow(&mut self) {
- error!("Meow");
+ println!("Meow");
self.meows += 1u;
if self.meows % 5u == 0u {
self.how_hungry += 1;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
use std::task::spawn;
struct Pair {
pub fn main() {
let (a, b) = f(22_u64, 44u16).f();
- info!("a={:?} b={:?}", a, b);
+ println!("a={:?} b={:?}", a, b);
assert_eq!(a, 22u64);
assert_eq!(b, 44u16);
}
let (tx, rx) = channel();
let _t = task::spawn(proc() { child(&tx) });
let y = rx.recv();
- error!("received");
- error!("{:?}", y);
+ println!("received");
+ println!("{:?}", y);
assert_eq!(y, 10);
}
fn child(c: &Sender<int>) {
- error!("sending");
+ println!("sending");
c.send(10);
- error!("value sent");
+ println!("value sent");
}
pub fn main() {
let x: int = 2 + 2;
- info!("{}", x);
- info!("hello, world");
- info!("{}", 10);
+ println!("{}", x);
+ println!("hello, world");
+ println!("{}", 10);
}
// compile-flags: --cfg ndebug
// exec-env:RUST_LOG=conditional-debug-macro-off=4
+#[feature(phase)];
+#[phase(syntax, link)]
+extern crate log;
+
pub fn main() {
- // only fails if debug! evaluates its argument.
+ // only fails if println! evaluates its argument.
debug!("{:?}", { if true { fail!() } });
}
// exec-env:RUST_LOG=conditional-debug-macro-on=4
pub fn main() {
- // exits early if debug! evaluates its arguments, otherwise it
+ // exits early if println! evaluates its arguments, otherwise it
// will hit the fail.
- debug!("{:?}", { if true { return; } });
+ println!("{:?}", { if true { return; } });
fail!();
}
static i: int = 10;
-pub fn main() { info!("{}", i); }
+pub fn main() { println!("{}", i); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-test #12920
-
-
-pub fn main() { if 1 == 1 { return; } info!("Paul is dead"); }
+pub fn main() { if 1 == 1 { return; } println!("Paul is dead"); }
pub fn main() {
let x = @Cell::new(5);
x.set(1000);
- info!("{:?}", x.get());
+ println!("{:?}", x.get());
}
let v = &"hello";
let y : &str = &"there";
- info!("{}", x);
- info!("{}", y);
+ println!("{}", x);
+ println!("{}", y);
assert_eq!(x[0], 'h' as u8);
assert_eq!(x[4], 'o' as u8);
let c = &"cccc";
let cc = &"ccccc";
- info!("{}", a);
+ println!("{}", a);
assert!(a < b);
assert!(a <= b);
assert!(b >= a);
assert!(b > a);
- info!("{}", b);
+ println!("{}", b);
assert!(a < c);
assert!(a <= c);
assert!(c >= a);
assert!(c > a);
- info!("{}", c);
+ println!("{}", c);
assert!(c < cc);
assert!(c <= cc);
assert!(cc >= c);
assert!(cc > c);
- info!("{}", cc);
+ println!("{}", cc);
}
let c : &[int] = &[2,2,2,2,3];
let cc : &[int] = &[2,2,2,2,2,2];
- info!("{:?}", a);
+ println!("{:?}", a);
assert!(a < b);
assert!(a <= b);
assert!(b >= a);
assert!(b > a);
- info!("{:?}", b);
+ println!("{:?}", b);
assert!(b < c);
assert!(b <= c);
assert!(c >= a);
assert!(c > a);
- info!("{:?}", c);
+ println!("{:?}", c);
assert!(a < cc);
assert!(a <= cc);
assert!(cc >= a);
assert!(cc > a);
- info!("{:?}", cc);
+ println!("{:?}", cc);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
/**
* A function that returns a hash of a value
*
pub fn y() { super::super::foo::x(); }
}
- pub fn x() { info!("x"); }
+ pub fn x() { println!("x"); }
}
pub fn main() { self::foo::bar::y(); }
}
pub mod bar {
- pub fn x() { info!("x"); }
+ pub fn x() { println!("x"); }
}
pub fn main() { foo::x(); }
fn test_box() {
fn compare_box(b1: @bool, b2: @bool) -> bool {
- info!("{}", *b1);
- info!("{}", *b2);
+ println!("{}", *b1);
+ println!("{}", *b2);
return *b1 == *b2;
}
test_generic::<bool>(@true, compare_box);
fn test_box() {
fn compare_box(b1: ~bool, b2: ~bool) -> bool {
- info!("{}", *b1);
- info!("{}", *b2);
+ println!("{}", *b1);
+ println!("{}", *b2);
return *b1 == *b2;
}
test_generic::<bool>(~true, compare_box);
fn count(n: uint) -> uint {
unsafe {
- info!("n = {}", n);
+ println!("n = {}", n);
rustrt::rust_dbg_call(cb, n)
}
}
pub fn main() {
let result = count(1000u);
- info!("result = {}", result);
+ println!("result = {}", result);
assert_eq!(result, 1000u);
}
fn count(n: uint) -> uint {
unsafe {
- info!("n = {}", n);
+ println!("n = {}", n);
rustrt::rust_dbg_call(cb, n)
}
}
// has a large stack)
task::spawn(proc() {
let result = count(1000u);
- info!("result = {}", result);
+ println!("result = {}", result);
assert_eq!(result, 1000u);
});
}
fn fact(n: uint) -> uint {
unsafe {
- info!("n = {}", n);
+ println!("n = {}", n);
rustrt::rust_dbg_call(cb, n)
}
}
pub fn main() {
let result = fact(10u);
- info!("result = {}", result);
+ println!("result = {}", result);
assert_eq!(result, 3628800u);
}
fn count(n: uint) -> uint {
unsafe {
- info!("n = {}", n);
+ println!("n = {}", n);
rustrt::rust_dbg_call(cb, n)
}
}
// has a large stack)
task::spawn(proc() {
let result = count(12u);
- info!("result = {}", result);
+ println!("result = {}", result);
assert_eq!(result, 2048u);
});
}
fn fact(n: uint) -> uint {
unsafe {
- info!("n = {}", n);
+ println!("n = {}", n);
externcallback::rustrt::rust_dbg_call(externcallback::cb, n)
}
}
pub fn main() {
let result = fact(10u);
- info!("result = {}", result);
+ println!("result = {}", result);
assert_eq!(result, 3628800u);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
extern crate mystd = "std";
pub fn main() {}
for _ in range(0, 10u) {
task::spawn(proc() {
let result = count(5u);
- info!("result = {}", result);
+ println!("result = {}", result);
assert_eq!(result, 16u);
});
}
fn f(x: int) -> int {
- // info!("in f:");
+ // println!("in f:");
- info!("{}", x);
+ println!("{}", x);
if x == 1 {
- // info!("bottoming out");
+ // println!("bottoming out");
return 1;
} else {
- // info!("recurring");
+ // println!("recurring");
let y: int = x * f(x - 1);
- // info!("returned");
+ // println!("returned");
- info!("{}", y);
+ println!("{}", y);
return y;
}
}
pub fn main() {
assert_eq!(f(5), 120);
- // info!("all done");
+ // println!("all done");
}
}
pub fn main() {
- error!("{}", match red {
+ println!("{}", match red {
red => { 1 }
green => { 2 }
blue => { 3 }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::num::Float;
pub fn main() {
fn foo(n: f64) -> f64 { return n + 0.12345; }
let n: f64 = 0.1;
let m: f64 = foo(n);
- info!("{}", m);
+ println!("{}", m);
}
pub fn main() {
let pi = 3.1415927;
- info!("{:?}", -pi * (pi + 2.0 / pi) - pi * 5.0);
+ println!("{:?}", -pi * (pi + 2.0 / pi) - pi * 5.0);
if pi == 5.0 || pi < 10.0 || pi <= 2.0 || pi != 22.0 / 7.0 || pi >= 10.0
|| pi > 1.0 {
- info!("yes");
+ println!("yes");
}
}
// except according to those terms.
fn f() {
- info!("This is a bare function");
+ println!("This is a bare function");
}
pub fn main() {
let mut j: int = 0;
pairs(|p| {
let (_0, _1) = p;
- info!("{}", _0);
- info!("{}", _1);
+ println!("{}", _0);
+ println!("{}", _1);
assert_eq!(_0 + 10, i);
i += 1;
j = _1;
pub fn main() {
let mut sum: int = 0;
- first_ten(|i| { info!("main"); info!("{}", i); sum = sum + i; });
- info!("sum");
- info!("{}", sum);
+ first_ten(|i| { println!("main"); println!("{}", i); sum = sum + i; });
+ println!("sum");
+ println!("{}", sum);
assert_eq!(sum, 45);
}
fn first_ten(it: |int|) {
let mut i: int = 0;
- while i < 10 { info!("first_ten"); it(i); i = i + 1; }
+ while i < 10 { println!("first_ten"); it(i); i = i + 1; }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
mod libc {
use std::libc::{c_char, size_t};
pub fn main() {
let expected = @100;
let actual = id::<@int>(expected);
- info!("{:?}", *actual);
+ println!("{:?}", *actual);
assert_eq!(*expected, *actual);
}
pub fn main() {
let expected = ~100;
let actual = id::<~int>(expected.clone());
- info!("{:?}", *actual);
+ println!("{:?}", *actual);
assert_eq!(*expected, *actual);
}
pub fn main() {
let b = f::<int>(10);
- info!("{:?}" ,b.a);
- info!("{:?}", b.b);
+ println!("{:?}" ,b.a);
+ println!("{:?}", b.b);
assert_eq!(b.a, 10);
assert_eq!(b.b, 10);
}
fn f<T>(x: @T) -> @T { return x; }
-pub fn main() { let x = f(@3); info!("{:?}", *x); }
+pub fn main() { let x = f(@3); println!("{:?}", *x); }
fn f<T>(x: ~T) -> ~T { return x; }
-pub fn main() { let x = f(~3); info!("{:?}", *x); }
+pub fn main() { let x = f(~3); println!("{:?}", *x); }
let p: Triple = Triple {x: 65, y: 66, z: 67};
let mut q: Triple = Triple {x: 68, y: 69, z: 70};
y = id::<int>(x);
- info!("{}", y);
+ println!("{}", y);
assert_eq!(x, y);
b = id::<char>(a);
- info!("{}", b);
+ println!("{}", b);
assert_eq!(a, b);
q = id::<Triple>(p);
x = p.z;
y = q.z;
- info!("{}", y);
+ println!("{}", y);
assert_eq!(x, y);
}
fn altfoo<T>(f: foo<T>) {
let mut hit = false;
- match f { arm::<T>(_x) => { info!("in arm"); hit = true; } }
+ match f { arm::<T>(_x) => { println!("in arm"); hit = true; } }
assert!((hit));
}
pub fn main() {
let nop: noption<int> = some::<int>(5);
- match nop { some::<int>(n) => { info!("{:?}", n); assert!((n == 5)); } }
+ match nop { some::<int>(n) => { println!("{:?}", n); assert!((n == 5)); } }
let nop2: noption<Pair> = some(Pair{x: 17, y: 42});
match nop2 {
some(t) => {
- info!("{:?}", t.x);
- info!("{:?}", t.y);
+ println!("{:?}", t.x);
+ println!("{:?}", t.y);
assert_eq!(t.x, 17);
assert_eq!(t.y, 42);
}
fn mk() -> int { return 1; }
-fn chk(a: int) { info!("{}", a); assert!((a == 1)); }
+fn chk(a: int) { println!("{}", a); assert!((a == 1)); }
fn apply<T>(produce: fn() -> T,
consume: fn(T)) {
fn get_third<T>(t: (T, T, T)) -> T { let (_, _, x) = t; return x; }
pub fn main() {
- info!("{:?}", get_third((1, 2, 3)));
+ println!("{:?}", get_third((1, 2, 3)));
assert_eq!(get_third((1, 2, 3)), 3);
assert_eq!(get_third((5u8, 6u8, 7u8)), 7u8);
}
#[feature(macro_rules)];
-extern crate extra;
extern crate glob;
use glob::glob;
-use extra::tempfile::TempDir;
use std::unstable::finally::Finally;
use std::{os, unstable};
use std::io;
+use std::io::TempDir;
macro_rules! assert_eq ( ($e1:expr, $e2:expr) => (
if $e1 != $e2 {
return;
}
let (tx, rx) = channel();
- error!("sending find_reducer");
+ println!("sending find_reducer");
ctrl.send(find_reducer(key.as_bytes().to_owned(), tx));
- error!("receiving");
+ println!("receiving");
let c = rx.recv();
- error!("{:?}", c);
+ println!("{:?}", c);
im.insert(key, c);
}
pub fn main() {
let i: int = if false { fail!() } else { 5 };
- info!("{:?}", i);
+ println!("{:?}", i);
}
fn foo(x: uint) {
if even(x) {
- info!("{}", x);
+ println!("{}", x);
} else {
fail!();
}
#[feature(macro_rules)];
#[deny(warnings)];
#[allow(unused_must_use)];
+#[allow(deprecated_owned_vector)];
use std::fmt;
use std::io::MemWriter;
use dug::too::greedily::and::too::deep::*;
mod module_of_many_things {
- pub fn f1() { info!("f1"); }
- pub fn f2() { info!("f2"); }
- fn f3() { info!("f3"); }
- pub fn f4() { info!("f4"); }
+ pub fn f1() { println!("f1"); }
+ pub fn f2() { println!("f2"); }
+ fn f3() { println!("f3"); }
+ pub fn f4() { println!("f4"); }
}
mod dug {
pub mod and {
pub mod too {
pub mod deep {
- pub fn nameless_fear() { info!("Boo!"); }
- pub fn also_redstone() { info!("Whatever."); }
+ pub fn nameless_fear() { println!("Boo!"); }
+ pub fn also_redstone() { println!("Whatever."); }
}
}
}
#[feature(globs)];
#[allow(dead_assignment)];
-extern crate extra;
use std::vec::*;
pub fn main() {
// except according to those terms.
mod foo {
- pub fn x(y: int) { info!("{:?}", y); }
+ pub fn x(y: int) { println!("{:?}", y); }
}
mod bar {
use zed::bar;
mod zed {
- pub fn bar() { info!("bar"); }
+ pub fn bar() { println!("bar"); }
}
pub fn main() { bar(); }
mod baz {
pub mod zed {
- pub fn bar() { info!("bar2"); }
+ pub fn bar() { println!("bar2"); }
}
}
use zed::bar;
mod zed {
- pub fn bar() { info!("bar"); }
+ pub fn bar() { println!("bar"); }
}
pub fn main() { let _zed = 42; bar(); }
mod foo {
pub use foo::zed::bar;
pub mod zed {
- pub fn bar() { info!("foo"); }
+ pub fn bar() { println!("foo"); }
}
}
mod foo {
pub mod zed {
- pub fn baz() { info!("baz"); }
+ pub fn baz() { println!("baz"); }
}
}
mod bar {
mod foo {
pub mod zed {
- pub fn baz() { info!("baz"); }
+ pub fn baz() { println!("baz"); }
}
}
mod bar {
use z = foo::x;
mod foo {
- pub fn x(y: int) { info!("{}", y); }
+ pub fn x(y: int) { println!("{}", y); }
}
pub fn main() { x(10); z(10); }
*/
// ignore-test
-extern crate extra;
-
fn loopy(n: int) {
if n > 0 { spawn(proc() { loopy(n - 1) }); spawn(proc() { loopy(n - 1) }); }
loop { }
mod inner {
pub mod inner2 {
- pub fn hello() { info!("hello, modular world"); }
+ pub fn hello() { println!("hello, modular world"); }
}
pub fn hello() { inner2::hello(); }
}
assert_eq!(v[3i8], 3);
assert_eq!(v[3u32], 3);
assert_eq!(v[3i32], 3);
- info!("{}", v[3u8]);
+ println!("{}", v[3u8]);
assert_eq!(s[3u], 'd' as u8);
assert_eq!(s[3u8], 'd' as u8);
assert_eq!(s[3i8], 'd' as u8);
assert_eq!(s[3u32], 'd' as u8);
assert_eq!(s[3i32], 'd' as u8);
- info!("{}", s[3u8]);
+ println!("{}", s[3u8]);
}
#[feature(globs)];
-extern crate extra;
-
mod rusti {
extern "rust-intrinsic" {
pub fn ctpop8(x: i8) -> i8;
let args = os::args();
if args.len() > 1 && args[1] == ~"child" {
for _ in range(0, 1000) {
- error!("hello?");
+ println!("hello?");
}
for _ in range(0, 1000) {
println!("hello?");
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-fast
+
+extern crate collections;
+
+use collections::HashSet;
+
+#[deriving(Eq, Hash)]
+struct XYZ {
+ x: int,
+ y: int,
+ z: int
+}
+
+fn main() {
+ let mut connected = HashSet::new();
+ let mut border = HashSet::new();
+
+ let middle = XYZ{x: 0, y: 0, z: 0};
+ border.insert(middle);
+
+ while border.len() > 0 && connected.len() < 10000 {
+ let choice = *(border.iter().next().unwrap());
+ border.remove(&choice);
+ connected.insert(choice);
+
+ let cxp = XYZ{x: choice.x + 1, y: choice.y, z: choice.z};
+ let cxm = XYZ{x: choice.x - 1, y: choice.y, z: choice.z};
+ let cyp = XYZ{x: choice.x, y: choice.y + 1, z: choice.z};
+ let cym = XYZ{x: choice.x, y: choice.y - 1, z: choice.z};
+ let czp = XYZ{x: choice.x, y: choice.y, z: choice.z + 1};
+ let czm = XYZ{x: choice.x, y: choice.y, z: choice.z - 1};
+
+ if !connected.contains(&cxp) {
+ border.insert(cxp);
+ }
+ if !connected.contains(&cxm){
+ border.insert(cxm);
+ }
+ if !connected.contains(&cyp){
+ border.insert(cyp);
+ }
+ if !connected.contains(&cym) {
+ border.insert(cym);
+ }
+ if !connected.contains(&czp){
+ border.insert(czp);
+ }
+ if !connected.contains(&czm) {
+ border.insert(czm);
+ }
+ }
+}
pub fn main() {
let mut m = HashMap::new();
m.insert("foo".as_bytes().to_owned(), "bar".as_bytes().to_owned());
- error!("{:?}", m);
+ println!("{:?}", m);
}
break;
}
- error!("{:?}", x);
+ println!("{:?}", x);
assert_eq!(x, 42);
}
}
fn meow() {
- error!("meow")
+ println!("meow")
}
fn cat() -> cat {
fn client(chan: pingpong::client::ping) {
let chan = pingpong::client::do_ping(chan);
- error!("Sent ping");
+ println!("Sent ping");
let (_chan, _data) = pingpong::client::do_pong(chan);
- error!("Received pong");
+ println!("Received pong");
}
fn server(chan: pingpong::server::ping) {
let (chan, _data) = pingpong::server::do_ping(chan);
- error!("Received ping");
+ println!("Received ping");
let _chan = pingpong::server::do_pong(chan);
- error!("Sent pong");
+ println!("Sent pong");
}
pub fn main() {
use collections::HashMap;
fn add_interfaces(managed_ip: ~str, device: HashMap<~str, int>) {
- error!("{}, {:?}", managed_ip, device.get(&~"interfaces"));
+ println!("{}, {:?}", managed_ip, device.get(&~"interfaces"));
}
pub fn main() {}
(*s).clone()
}
option::Some(value) => {
- error!("{} was expected to be a string but is a {:?}", key, value);
+ println!("{} was expected to be a string but is a {:?}", key, value);
default
}
option::None => {
(label, bool_value(false))
}
_ => {
- error!("Expected dict for {} interfaces but found {:?}", managed_ip, data);
+ println!("Expected dict for {} interfaces but found {:?}", managed_ip, data);
(~"gnos:missing-interface", bool_value(true))
}
}
}
_ =>
{
- error!("Expected list for {} interfaces but found {:?}", managed_ip,
+ println!("Expected list for {} interfaces but found {:?}", managed_ip,
device.get(&~"interfaces"));
~[]
}
/// Map representation
-extern crate extra;
-
use std::io;
use std::fmt;
'.' => { earth }
' ' => { empty }
_ => {
- error!("invalid square: {:?}", c);
+ println!("invalid square: {:?}", c);
fail!()
}
}
// x.f();
// y.f();
// (*z).f();
- error!("ok so far...");
+ println!("ok so far...");
z.f(); //segfault
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::vec;
trait methods {
// except according to those terms.
pub fn main() {
- error!("{:?}", ("hi there!", "you"));
+ println!("{:?}", ("hi there!", "you"));
}
// except according to those terms.
// rustc --test ignores2.rs && ./ignores2
-extern crate extra;
use std::path::{Path};
use std::path;
#[feature(managed_boxes)];
-extern crate extra;
-
enum Token {
Text(@~str),
ETag(@~[~str], @~str),
// However the extra library is designed to be optional (for code that must run on constrained
// environments like embedded devices or special environments like kernel code) so it must
// be explicitly linked in.
-extern crate extra;
// Extern mod controls linkage. Use controls the visibility of names to modules that are
// already linked in. Using WriterUtil allows us to use the write_line method.
#[allow(unnecessary_allocation)];
// rustc --test match_borrowed_str.rs.rs && ./match_borrowed_str.rs
-extern crate extra;
fn compare(x: &str, y: &str) -> bool
{
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::task;
type RingBuffer = ~[f64];
let mut samples_chan = samples_chan;
let callback: SamplesFn = proc(buffer) {
for i in range(0u, buffer.len()) {
- error!("{}: {}", i, buffer[i])
+ println!("{}: {}", i, buffer[i])
}
};
samples_chan.send(GetSamples(name.clone(), callback));
unsafe {
libc::exit(0);
}
- error!("ack");
+ println!("ack");
}
let a = A { x: 0 };
let A { x: ref x } = a;
- info!("{:?}", x)
+ println!("{:?}", x)
}
match a {
A { x : ref x } => {
- info!("{:?}", x)
+ println!("{:?}", x)
}
}
}
let sa = A { a: 100 };
let sb = B { b: 200, pa: &sa };
- debug!("sa is {:?}", sa);
- debug!("sb is {:?}", sb);
- debug!("sb.pa is {:?}", sb.get_pa());
+ println!("sa is {:?}", sa);
+ println!("sb is {:?}", sb);
+ println!("sb.pa is {:?}", sb.get_pa());
}
fn test_stack_assign() {
let s: ~str = ~"a";
- info!("{}", s.clone());
+ println!("{}", s.clone());
let t: ~str = ~"a";
assert!(s == t);
let u: ~str = ~"b";
assert!((s != u));
}
-fn test_heap_log() { let s = ~"a big ol' string"; info!("{}", s); }
+fn test_heap_log() { let s = ~"a big ol' string"; println!("{}", s); }
fn test_stack_add() {
assert_eq!(~"a" + "b", ~"ab");
let mut s = ~"a";
s.push_str("b");
- info!("{}", s.clone());
+ println!("{}", s.clone());
assert_eq!(s, ~"ab");
let mut s = ~"c";
#[attr3];
#[attr4(attr5)];
-#[crate_id="extra#0.1"];
+#[crate_id="foobar#0.1"];
// These are attributes of the following mod
#[attr1 = "val"]
}
mod test_distinguish_syntax_ext {
- extern crate extra;
-
pub fn f() {
format!("test{}", "s");
#[attr = "val"]
pub fn main() {
let mut sum: int = 0;
range_(0, 100, |x| sum += x );
- info!("{}", sum);
+ println!("{}", sum);
}
pub fn main() {
let mut e = Refs{refs: ~[], n: 0};
- let _f: || = || error!("{}", e.n);
+ let _f: || = || println!("{}", e.n);
let x: &[int] = e.refs;
assert_eq!(x.len(), 0);
}
fn invoke(f: ||) { f(); }
let k = ~22;
let _u = A {a: k.clone()};
- invoke(|| error!("{:?}", k.clone()) )
+ invoke(|| println!("{:?}", k.clone()) )
}
let x = 1 == 2 || 3 == 3;
assert!((x));
let mut y: int = 10;
- info!("{:?}", x || incr(&mut y));
+ println!("{:?}", x || incr(&mut y));
assert_eq!(y, 10);
if true && x { assert!((true)); } else { assert!((false)); }
}
-fn foo(x: int) { info!("{}", x); }
+fn foo(x: int) { println!("{}", x); }
pub fn main() { let mut x: int; if 1 > 2 { x = 12; } else { x = 10; } foo(x); }
pub fn main() {
let x = ~[1, 2, 3];
let mut y = 0;
- for i in x.iter() { info!("{:?}", *i); y += *i; }
- info!("{:?}", y);
+ for i in x.iter() { println!("{:?}", *i); y += *i; }
+ println!("{:?}", y);
assert_eq!(y, 6);
let s = ~"hello there";
let mut i: int = 0;
// ...
i += 1;
- info!("{:?}", i);
- info!("{:?}", c);
+ println!("{:?}", i);
+ println!("{:?}", c);
}
assert_eq!(i, 11);
}
v = 3;
break;
}
- info!("{}", v);
+ println!("{}", v);
}
pub fn main() {
-pub fn main() { if false { error!("{}", ~"foo" + "bar"); } }
+pub fn main() { if false { println!("{}", ~"foo" + "bar"); } }
}
pub fn main() {
- info!("{}", 1);
- info!("{}", 2.0);
- warn!("{:?}", Three);
- error!("{:?}", ~[4]);
+ println!("{}", 1);
+ println!("{}", 2.0);
+ println!("{:?}", Three);
+ println!("{:?}", ~[4]);
}
// compile-flags:--cfg ndebug
// exec-env:RUST_LOG=logging-enabled-debug=debug
-use std::logging;
+#[feature(phase)];
+#[phase(syntax, link)]
+extern crate log;
pub fn main() {
- if log_enabled!(logging::DEBUG) {
+ if log_enabled!(log::DEBUG) {
fail!("what?! debugging?");
}
}
// ignore-fast
// exec-env:RUST_LOG=logging-enabled=info
-use std::logging;
+#[feature(phase)];
+#[phase(syntax, link)]
+extern crate log;
pub fn main() {
- if log_enabled!(logging::DEBUG) {
+ if log_enabled!(log::DEBUG) {
fail!("what?! debugging?");
}
- if !log_enabled!(logging::INFO) {
+ if !log_enabled!(log::INFO) {
fail!("what?! no info?");
}
}
let (tx, rx) = channel();
spawn(proc() {
let mut f = Foo(Cell::new(0));
- debug!("{}", f);
+ println!("{}", f);
let Foo(ref mut f) = f;
assert!(f.get() == 1);
tx.send(());
pub fn main() {
let mut i = 0u;
loop {
- error!("a");
+ println!("a");
i += 1u;
if i == 10u {
break;
if i == 21u {
break;
}
- error!("b");
+ println!("b");
is_even = false;
i += 1u;
if i % 2u != 0u {
}
assert!(!is_even);
loop {
- error!("c");
+ println!("c");
if i == 22u {
break;
}
pub fn main() {
spawn! {
- info!("stmt");
+ println!("stmt");
};
let _ = spawn! {
- info!("expr");
+ println!("expr");
};
}
pub fn main() {
let i: int =
match Some::<int>(3) { None::<int> => { fail!() } Some::<int>(_) => { 5 } };
- info!("{}", i);
+ println!("{}", i);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-extern crate extra;
-
fn foo<T>(y: Option<T>) {
let mut x: int;
let mut rs: ~[int] = ~[];
return;
}
-pub fn main() { info!("hello"); foo::<int>(Some::<int>(5)); }
+pub fn main() { println!("hello"); foo::<int>(Some::<int>(5)); }
enum t { make_t(@int), clam, }
fn foo(s: @int) {
- info!("{:?}", ::std::managed::refcount(s));
+ println!("{:?}", ::std::managed::refcount(s));
let count = ::std::managed::refcount(s);
let x: t = make_t(s); // ref up
assert_eq!(::std::managed::refcount(s), count + 1u);
- info!("{:?}", ::std::managed::refcount(s));
+ println!("{:?}", ::std::managed::refcount(s));
match x {
make_t(y) => {
- info!("{:?}", y); // ref up then down
+ println!("{:?}", y); // ref up then down
}
- _ => { info!("?"); fail!(); }
+ _ => { println!("?"); fail!(); }
}
- info!("{:?}", ::std::managed::refcount(s));
+ println!("{:?}", ::std::managed::refcount(s));
assert_eq!(::std::managed::refcount(s), count + 1u);
let _ = ::std::managed::refcount(s); // don't get bitten by last-use.
}
foo(s); // ref up then down
- info!("{}", ::std::managed::refcount(s));
+ println!("{}", ::std::managed::refcount(s));
let count2 = ::std::managed::refcount(s);
assert_eq!(count, count2);
}
fn altlit(f: int) -> int {
match f {
- 10 => { info!("case 10"); return 20; }
- 11 => { info!("case 11"); return 22; }
+ 10 => { println!("case 10"); return 20; }
+ 11 => { println!("case 11"); return 22; }
_ => fail!("the impossible happened")
}
}
fn foo(x: maybe<int>) {
match x {
- nothing => { error!("A"); }
- just(_a) => { error!("B"); }
+ nothing => { println!("A"); }
+ just(_a) => { println!("B"); }
}
}
pub fn main() {
match ~100 {
~x => {
- info!("{:?}", x);
+ println!("{:?}", x);
assert_eq!(x, 100);
}
}
Some(num) => num as u32
};
assert_eq!(f, 1234u32);
- error!("{}", f)
+ println!("{}", f)
}
#[feature(managed_boxes)];
-extern crate extra;
-
trait Serializer {
}
// This test will call __morestack with various minimum stack sizes
-extern crate extra;
-
use std::task;
fn getbig(i: int) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
#[deriving(Clone)]
struct Triple {
x: int,
#[feature(managed_boxes)];
-extern crate extra;
-
struct Triple { x: int, y: int, z: int }
fn test(x: bool, foo: @Triple) -> int {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
struct Triple {a: int, b: int, c: int}
fn test(foo: ~Triple) -> ~Triple {
#[feature(managed_boxes)];
-extern crate extra;
-
struct Triple { a: int, b: int, c: int }
fn test(foo: @Triple) -> @Triple {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
fn grow(v: &mut ~[int]) {
v.push(1);
}
grow(&mut v);
grow(&mut v);
let len = v.len();
- info!("{}", len);
+ println!("{}", len);
assert_eq!(len, 3 as uint);
}
Some::<int>(_x) => {
let mut bar;
match None::<int> { None::<int> => { bar = 5; } _ => { baz(); } }
- info!("{:?}", bar);
+ println!("{:?}", bar);
}
- None::<int> => { info!("hello"); }
+ None::<int> => { println!("hello"); }
}
}
fn nested(o: t) {
match o {
- bar(_i, Some::<int>(_)) => { error!("wrong pattern matched"); fail!(); }
- _ => { error!("succeeded"); }
+ bar(_i, Some::<int>(_)) => { println!("wrong pattern matched"); fail!(); }
+ _ => { println!("succeeded"); }
}
}
pub fn main() {
let mut x: int = 1;
x *= 2;
- info!("{}", x);
+ println!("{}", x);
assert_eq!(x, 2);
x += 3;
- info!("{}", x);
+ println!("{}", x);
assert_eq!(x, 5);
x *= x;
- info!("{}", x);
+ println!("{}", x);
assert_eq!(x, 25);
x /= 5;
- info!("{}", x);
+ println!("{}", x);
assert_eq!(x, 5);
}
while b <= 32u {
0u << b;
b <<= 1u;
- info!("{:?}", b);
+ println!("{:?}", b);
}
}
pub fn main() {
let x = true;
if x { let mut i = 10; while i > 0 { i -= 1; } }
- match x { true => { info!("right"); } false => { info!("wrong"); } }
+ match x { true => { println!("right"); } false => { println!("wrong"); } }
}
#[allow(unreachable_code)];
-fn dont_call_me() { fail!(); info!("{}", 1); }
+// ignore-test #12920
+
+fn dont_call_me() { fail!(); println!("{}", 1); }
pub fn main() { }
#[feature(managed_boxes)];
-fn magic(x: A) { info!("{:?}", x); }
-fn magic2(x: @int) { info!("{:?}", x); }
+fn magic(x: A) { println!("{:?}", x); }
+fn magic2(x: @int) { println!("{:?}", x); }
struct A { a: @int }
// This checks that preemption works.
// note: halfway done porting to modern rust
-extern crate extra;
-
use std::comm;
-use extra::comm;
fn starve_main(alive: Receiver<int>) {
- info!("signalling main");
+ println!("signalling main");
alive.recv();
- info!("starving main");
+ println!("starving main");
let mut i: int = 0;
loop { i += 1; }
}
pub fn main() {
let (port, chan) = stream();
- info!("main started");
+ println!("main started");
spawn(proc() {
starve_main(port);
});
let mut i: int = 0;
- info!("main waiting for alive signal");
+ println!("main waiting for alive signal");
chan.send(i);
- info!("main got alive signal");
- while i < 50 { info!("main iterated"); i += 1; }
- info!("main completed");
+ println!("main got alive signal");
+ while i < 50 { println!("main iterated"); i += 1; }
+ println!("main completed");
}
fn something(f: ||) { f(); }
pub fn main() {
- something(|| error!("hi!") );
+ something(|| println!("hi!") );
}
let x = @6;
let y = x.get();
- info!("y={}", y);
+ println!("y={}", y);
assert_eq!(y, 6);
let x = ~6;
let y = x.get();
- info!("y={}", y);
+ println!("y={}", y);
assert_eq!(y, 6);
let x = &6;
let y = x.get();
- info!("y={}", y);
+ println!("y={}", y);
assert_eq!(y, 6);
}
pub fn main() {
let x = ~[1, 2, 3];
let y = call_sum(x);
- info!("y=={}", y);
+ println!("y=={}", y);
assert_eq!(y, 6);
let x = ~[1, 2, 3];
let y = x.sum_();
- info!("y=={}", y);
+ println!("y=={}", y);
assert_eq!(y, 6);
let x = ~[1, 2, 3];
let y = x.sum_();
- info!("y=={}", y);
+ println!("y=={}", y);
assert_eq!(y, 6);
}
// Send it through the shape code
let y = format!("{:?}", x);
- info!("align inner = {:?}", rusti::min_align_of::<Inner>());
- info!("size outer = {:?}", mem::size_of::<Outer>());
- info!("y = {}", y);
+ println!("align inner = {:?}", rusti::min_align_of::<Inner>());
+ println!("size outer = {:?}", mem::size_of::<Outer>());
+ println!("y = {}", y);
// per clang/gcc the alignment of `inner` is 4 on x86.
assert_eq!(rusti::min_align_of::<Inner>(), m::align());
// Send it through the shape code
let y = format!("{:?}", x);
- info!("align inner = {}", rusti::min_align_of::<Inner>());
- info!("size outer = {}", mem::size_of::<Outer>());
- info!("y = {}", y);
+ println!("align inner = {}", rusti::min_align_of::<Inner>());
+ println!("size outer = {}", mem::size_of::<Outer>());
+ println!("y = {}", y);
// per clang/gcc the alignment of `Inner` is 4 on x86.
assert_eq!(rusti::min_align_of::<Inner>(), m::m::align());
pub fn main() {
let x = X {foo: ~"hello", bar: ~"world"};
- info!("{}", x.foo.clone());
- info!("{}", x.bar.clone());
+ println!("{}", x.foo.clone());
+ println!("{}", x.bar.clone());
}
impl TyVisitor for MyVisitor {
fn visit_bot(&mut self) -> bool {
self.types.push(~"bot");
- error!("visited bot type");
+ println!("visited bot type");
true
}
fn visit_nil(&mut self) -> bool {
self.types.push(~"nil");
- error!("visited nil type");
+ println!("visited nil type");
true
}
fn visit_bool(&mut self) -> bool {
self.types.push(~"bool");
- error!("visited bool type");
+ println!("visited bool type");
true
}
fn visit_int(&mut self) -> bool {
self.types.push(~"int");
- error!("visited int type");
+ println!("visited int type");
true
}
fn visit_i8(&mut self) -> bool {
self.types.push(~"i8");
- error!("visited i8 type");
+ println!("visited i8 type");
true
}
fn visit_i16(&mut self) -> bool {
self.types.push(~"i16");
- error!("visited i16 type");
+ println!("visited i16 type");
true
}
fn visit_i32(&mut self) -> bool { true }
pub fn main() {
let three = &3;
- error!("{}", *f(three));
+ println!("{}", *f(three));
}
pub fn main() {
let p = @22u;
let r = foo(p);
- info!("r={}", r);
+ println!("r={}", r);
assert_eq!(r, 22u);
}
// This test verifies that temporary lifetime is correctly computed
// for static objects in enclosing scopes.
-extern crate extra;
use std::cmp::Eq;
fn f<T:Eq>(o: &mut Option<T>) {
pub fn main() {
let clam = Clam { chowder: &3 };
- info!("{:?}", *clam.get_chowder());
+ println!("{:?}", *clam.get_chowder());
clam.get_chowder();
}
match y {
int_wrapper_ctor(zz) => { z = zz; }
}
- info!("{:?}", *z);
+ println!("{:?}", *z);
}
let mut x: int = 3;
let y: &mut int = &mut x;
*y = 5;
- info!("{:?}", *y);
+ println!("{:?}", *y);
}
}
pub fn main() {
- let cl_box = box_it(|| info!("Hello, world!"));
+ let cl_box = box_it(|| println!("Hello, world!"));
call_static_closure(cl_box);
}
// because it needs TempDir, which is in extra
// ignore-fast
-extern crate extra;
-use extra::tempfile::TempDir;
+use std::io::TempDir;
use std::os;
use std::libc;
use std::io;
let x = [ [true], ..512 ];
let y = [ 0, ..1 ];
- error!("{:?}", x);
- error!("{:?}", y);
+ println!("{:?}", x);
+ println!("{:?}", y);
}
let a = r(i);
let b = (a, 10);
let (c, _d) = b;
- info!("{:?}", c);
+ println!("{:?}", c);
}
assert_eq!(i.get(), 1);
}
#[unsafe_destructor]
impl Drop for shrinky_pointer {
fn drop(&mut self) {
- error!("Hello!"); self.i.set(self.i.get() - 1);
+ println!("Hello!"); self.i.set(self.i.get() - 1);
}
}
pub fn main() {
let my_total = @@Cell::new(10);
{ let pt = shrinky_pointer(my_total); assert!((pt.look_at() == 10)); }
- error!("my_total = {}", my_total.get());
+ println!("my_total = {}", my_total.get());
assert_eq!(my_total.get(), 9);
}
-fn my_err(s: ~str) -> ! { error!("{:?}", s); fail!(); }
+fn my_err(s: ~str) -> ! { println!("{:?}", s); fail!(); }
fn okay(i: uint) -> int {
if i == 3u { my_err(~"I don't like three"); } else { return 42; }
fn test05() {
let three = ~3;
let fn_to_send: proc(int) = proc(n) {
- error!("{}", *three + n); // will copy x into the closure
+ println!("{}", *three + n); // will copy x into the closure
assert_eq!(*three, 3);
};
task::spawn(proc() {
match none::<int> {
some::<int>(_) => {
for _i in c.iter() {
- info!("{:?}", a);
+ println!("{:?}", a);
let a = 17;
b.push(a);
}
let p_: Path_ = Path_ { global: true, idents: ~[~"hi"], types: ~[t] };
let p: path = Spanned { data: p_, span: sp };
let x = X { sp: sp, path: p };
- error!("{:?}", x.path.clone());
- error!("{:?}", x.clone());
+ println!("{:?}", x.path.clone());
+ println!("{:?}", x.clone());
}
-pub fn main() { let mut n; n = 1; info!("{}", n); }
+pub fn main() { let mut n; n = 1; println!("{}", n); }
pub fn main() {
let x = none::<int>;
- match x { none::<int> => { info!("hello world"); } }
+ match x { none::<int> => { println!("hello world"); } }
}
fn uhoh<T>(v: ~[clam<T>]) {
match v[1] {
a::<T>(ref _t, ref u) => {
- info!("incorrect");
- info!("{:?}", u);
+ println!("incorrect");
+ println!("{:?}", u);
fail!();
}
- b::<T> => { info!("correct"); }
+ b::<T> => { println!("correct"); }
}
}
use std::task;
fn x(s: ~str, n: int) {
- info!("{:?}", s);
- info!("{:?}", n);
+ println!("{:?}", s);
+ println!("{:?}", n);
}
pub fn main() {
task::spawn(proc() x(~"hello from second spawned fn", 66) );
task::spawn(proc() x(~"hello from third spawned fn", 67) );
let mut i: int = 30;
- while i > 0 { i = i - 1; info!("parent sleeping"); task::deschedule(); }
+ while i > 0 { i = i - 1; println!("parent sleeping"); task::deschedule(); }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::task;
pub fn main() {
task::spawn(proc() child(10) );
}
-fn child(i: int) { error!("{}", i); assert!((i == 10)); }
+fn child(i: int) { println!("{}", i); assert!((i == 10)); }
fn child(args: (int, int, int, int, int, int, int, int, int)) {
let (i1, i2, i3, i4, i5, i6, i7, i8, i9) = args;
- error!("{}", i1);
- error!("{}", i2);
- error!("{}", i3);
- error!("{}", i4);
- error!("{}", i5);
- error!("{}", i6);
- error!("{}", i7);
- error!("{}", i8);
- error!("{}", i9);
+ println!("{}", i1);
+ println!("{}", i2);
+ println!("{}", i3);
+ println!("{}", i4);
+ println!("{}", i5);
+ println!("{}", i6);
+ println!("{}", i7);
+ println!("{}", i8);
+ println!("{}", i9);
assert_eq!(i1, 10);
assert_eq!(i2, 20);
assert_eq!(i3, 30);
// exec-env:RUST_LOG=debug
// ignore-fast
-// regression test for issue #10405, make sure we don't call debug! too soon.
+// regression test for issue #10405, make sure we don't call println! too soon.
use std::task;
// ignore-fast
-extern crate extra;
-
-use extra::tempfile;
-use std::io::File;
+use std::io::{File, TempDir};
pub fn main() {
- let dir = tempfile::TempDir::new_in(&Path::new("."), "").unwrap();
+ let dir = TempDir::new_in(&Path::new("."), "").unwrap();
let path = dir.path().join("file");
{
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-
-extern crate extra;
-
fn test1() {
let mut s: ~str = ~"hello";
s.push_str("world");
- info!("{}", s.clone());
+ println!("{}", s.clone());
assert_eq!(s[9], 'd' as u8);
}
let ff: ~str = ~"abc";
let a: ~str = ff + "ABC" + ff;
let b: ~str = ~"ABC" + ff + "ABC";
- info!("{}", a.clone());
- info!("{}", b.clone());
+ println!("{}", a.clone());
+ println!("{}", b.clone());
assert_eq!(a, ~"abcABCabc");
assert_eq!(b, ~"ABCabcABC");
}
let a: ~str = ~"hello";
let b: ~str = ~"world";
let s: ~str = a + b;
- info!("{}", s.clone());
+ println!("{}", s.clone());
assert_eq!(s[9], 'd' as u8);
}
pub fn main() {
let s = ~"hello";
let c: u8 = s[4];
- info!("{:?}", c);
+ println!("{:?}", c);
assert_eq!(c, 0x6f as u8);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-
-extern crate extra;
-
pub fn main() {
let a: ~str = ~"this \
is a test";
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
pub fn main() {
// Make sure we properly handle repeated self-appends.
let mut a: ~str = ~"A";
let mut i = 20;
let mut expected_len = 1u;
while i > 0 {
- error!("{}", a.len());
+ println!("{}", a.len());
assert_eq!(a.len(), expected_len);
a = a + a; // FIXME(#3387)---can't write a += a
i -= 1;
impl Drop for foo {
fn drop(&mut self) {
- error!("{}", self.x);
+ println!("{}", self.x);
}
}
c: 0xcccc_cccc_cccc_cccc_u64,
d: 0xdddd_dddd_dddd_dddd_u64 };
let qq = rustrt::rust_dbg_abi_1(q);
- error!("a: {:x}", qq.a as uint);
- error!("b: {:x}", qq.b as uint);
- error!("c: {:x}", qq.c as uint);
- error!("d: {:x}", qq.d as uint);
+ println!("a: {:x}", qq.a as uint);
+ println!("b: {:x}", qq.b as uint);
+ println!("c: {:x}", qq.c as uint);
+ println!("d: {:x}", qq.d as uint);
assert_eq!(qq.a, q.c + 1u64);
assert_eq!(qq.b, q.d - 1u64);
assert_eq!(qq.c, q.a + 1u64);
b: 0b_1010_1010_u8,
c: 1.0987654321e-15_f64 };
let ff = rustrt::rust_dbg_abi_2(f);
- error!("a: {}", ff.a as f64);
- error!("b: {}", ff.b as uint);
- error!("c: {}", ff.c as f64);
+ println!("a: {}", ff.a as f64);
+ println!("b: {}", ff.b as uint);
+ println!("c: {}", ff.c as f64);
assert_eq!(ff.a, f.c + 1.0f64);
assert_eq!(ff.b, 0xff_u8);
assert_eq!(ff.c, f.a - 1.0f64);
pub fn main() {
let f = 1 as *libc::FILE;
- info!("{}", f as int);
- info!("{}", f as uint);
- info!("{}", f as i8);
- info!("{}", f as i16);
- info!("{}", f as i32);
- info!("{}", f as i64);
- info!("{}", f as u8);
- info!("{}", f as u16);
- info!("{}", f as u32);
- info!("{}", f as u64);
-
- info!("{}", 1 as int);
- info!("{}", 1 as uint);
- info!("{}", 1 as *libc::FILE);
- info!("{}", 1 as i8);
- info!("{}", 1 as i16);
- info!("{}", 1 as i32);
- info!("{}", 1 as i64);
- info!("{}", 1 as u8);
- info!("{}", 1 as u16);
- info!("{}", 1 as u32);
- info!("{}", 1 as u64);
- info!("{}", 1 as f32);
- info!("{}", 1 as f64);
-
- info!("{}", 1u as int);
- info!("{}", 1u as uint);
- info!("{}", 1u as *libc::FILE);
- info!("{}", 1u as i8);
- info!("{}", 1u as i16);
- info!("{}", 1u as i32);
- info!("{}", 1u as i64);
- info!("{}", 1u as u8);
- info!("{}", 1u as u16);
- info!("{}", 1u as u32);
- info!("{}", 1u as u64);
- info!("{}", 1u as f32);
- info!("{}", 1u as f64);
-
- info!("{}", 1i8 as int);
- info!("{}", 1i8 as uint);
- info!("{}", 1i8 as *libc::FILE);
- info!("{}", 1i8 as i8);
- info!("{}", 1i8 as i16);
- info!("{}", 1i8 as i32);
- info!("{}", 1i8 as i64);
- info!("{}", 1i8 as u8);
- info!("{}", 1i8 as u16);
- info!("{}", 1i8 as u32);
- info!("{}", 1i8 as u64);
- info!("{}", 1i8 as f32);
- info!("{}", 1i8 as f64);
-
- info!("{}", 1u8 as int);
- info!("{}", 1u8 as uint);
- info!("{}", 1u8 as *libc::FILE);
- info!("{}", 1u8 as i8);
- info!("{}", 1u8 as i16);
- info!("{}", 1u8 as i32);
- info!("{}", 1u8 as i64);
- info!("{}", 1u8 as u8);
- info!("{}", 1u8 as u16);
- info!("{}", 1u8 as u32);
- info!("{}", 1u8 as u64);
- info!("{}", 1u8 as f32);
- info!("{}", 1u8 as f64);
-
- info!("{}", 1i16 as int);
- info!("{}", 1i16 as uint);
- info!("{}", 1i16 as *libc::FILE);
- info!("{}", 1i16 as i8);
- info!("{}", 1i16 as i16);
- info!("{}", 1i16 as i32);
- info!("{}", 1i16 as i64);
- info!("{}", 1i16 as u8);
- info!("{}", 1i16 as u16);
- info!("{}", 1i16 as u32);
- info!("{}", 1i16 as u64);
- info!("{}", 1i16 as f32);
- info!("{}", 1i16 as f64);
-
- info!("{}", 1u16 as int);
- info!("{}", 1u16 as uint);
- info!("{}", 1u16 as *libc::FILE);
- info!("{}", 1u16 as i8);
- info!("{}", 1u16 as i16);
- info!("{}", 1u16 as i32);
- info!("{}", 1u16 as i64);
- info!("{}", 1u16 as u8);
- info!("{}", 1u16 as u16);
- info!("{}", 1u16 as u32);
- info!("{}", 1u16 as u64);
- info!("{}", 1u16 as f32);
- info!("{}", 1u16 as f64);
-
- info!("{}", 1i32 as int);
- info!("{}", 1i32 as uint);
- info!("{}", 1i32 as *libc::FILE);
- info!("{}", 1i32 as i8);
- info!("{}", 1i32 as i16);
- info!("{}", 1i32 as i32);
- info!("{}", 1i32 as i64);
- info!("{}", 1i32 as u8);
- info!("{}", 1i32 as u16);
- info!("{}", 1i32 as u32);
- info!("{}", 1i32 as u64);
- info!("{}", 1i32 as f32);
- info!("{}", 1i32 as f64);
-
- info!("{}", 1u32 as int);
- info!("{}", 1u32 as uint);
- info!("{}", 1u32 as *libc::FILE);
- info!("{}", 1u32 as i8);
- info!("{}", 1u32 as i16);
- info!("{}", 1u32 as i32);
- info!("{}", 1u32 as i64);
- info!("{}", 1u32 as u8);
- info!("{}", 1u32 as u16);
- info!("{}", 1u32 as u32);
- info!("{}", 1u32 as u64);
- info!("{}", 1u32 as f32);
- info!("{}", 1u32 as f64);
-
- info!("{}", 1i64 as int);
- info!("{}", 1i64 as uint);
- info!("{}", 1i64 as *libc::FILE);
- info!("{}", 1i64 as i8);
- info!("{}", 1i64 as i16);
- info!("{}", 1i64 as i32);
- info!("{}", 1i64 as i64);
- info!("{}", 1i64 as u8);
- info!("{}", 1i64 as u16);
- info!("{}", 1i64 as u32);
- info!("{}", 1i64 as u64);
- info!("{}", 1i64 as f32);
- info!("{}", 1i64 as f64);
-
- info!("{}", 1u64 as int);
- info!("{}", 1u64 as uint);
- info!("{}", 1u64 as *libc::FILE);
- info!("{}", 1u64 as i8);
- info!("{}", 1u64 as i16);
- info!("{}", 1u64 as i32);
- info!("{}", 1u64 as i64);
- info!("{}", 1u64 as u8);
- info!("{}", 1u64 as u16);
- info!("{}", 1u64 as u32);
- info!("{}", 1u64 as u64);
- info!("{}", 1u64 as f32);
- info!("{}", 1u64 as f64);
-
- info!("{}", 1u64 as int);
- info!("{}", 1u64 as uint);
- info!("{}", 1u64 as *libc::FILE);
- info!("{}", 1u64 as i8);
- info!("{}", 1u64 as i16);
- info!("{}", 1u64 as i32);
- info!("{}", 1u64 as i64);
- info!("{}", 1u64 as u8);
- info!("{}", 1u64 as u16);
- info!("{}", 1u64 as u32);
- info!("{}", 1u64 as u64);
- info!("{}", 1u64 as f32);
- info!("{}", 1u64 as f64);
-
- info!("{}", true as int);
- info!("{}", true as uint);
- info!("{}", true as *libc::FILE);
- info!("{}", true as i8);
- info!("{}", true as i16);
- info!("{}", true as i32);
- info!("{}", true as i64);
- info!("{}", true as u8);
- info!("{}", true as u16);
- info!("{}", true as u32);
- info!("{}", true as u64);
- info!("{}", true as f32);
- info!("{}", true as f64);
-
- info!("{}", 1. as int);
- info!("{}", 1. as uint);
- info!("{}", 1. as i8);
- info!("{}", 1. as i16);
- info!("{}", 1. as i32);
- info!("{}", 1. as i64);
- info!("{}", 1. as u8);
- info!("{}", 1. as u16);
- info!("{}", 1. as u32);
- info!("{}", 1. as u64);
- info!("{}", 1. as f32);
- info!("{}", 1. as f64);
-
- info!("{}", 1f32 as int);
- info!("{}", 1f32 as uint);
- info!("{}", 1f32 as i8);
- info!("{}", 1f32 as i16);
- info!("{}", 1f32 as i32);
- info!("{}", 1f32 as i64);
- info!("{}", 1f32 as u8);
- info!("{}", 1f32 as u16);
- info!("{}", 1f32 as u32);
- info!("{}", 1f32 as u64);
- info!("{}", 1f32 as f32);
- info!("{}", 1f32 as f64);
-
- info!("{}", 1f64 as int);
- info!("{}", 1f64 as uint);
- info!("{}", 1f64 as i8);
- info!("{}", 1f64 as i16);
- info!("{}", 1f64 as i32);
- info!("{}", 1f64 as i64);
- info!("{}", 1f64 as u8);
- info!("{}", 1f64 as u16);
- info!("{}", 1f64 as u32);
- info!("{}", 1f64 as u64);
- info!("{}", 1f64 as f32);
- info!("{}", 1f64 as f64);
+ println!("{}", f as int);
+ println!("{}", f as uint);
+ println!("{}", f as i8);
+ println!("{}", f as i16);
+ println!("{}", f as i32);
+ println!("{}", f as i64);
+ println!("{}", f as u8);
+ println!("{}", f as u16);
+ println!("{}", f as u32);
+ println!("{}", f as u64);
+
+ println!("{}", 1 as int);
+ println!("{}", 1 as uint);
+ println!("{}", 1 as *libc::FILE);
+ println!("{}", 1 as i8);
+ println!("{}", 1 as i16);
+ println!("{}", 1 as i32);
+ println!("{}", 1 as i64);
+ println!("{}", 1 as u8);
+ println!("{}", 1 as u16);
+ println!("{}", 1 as u32);
+ println!("{}", 1 as u64);
+ println!("{}", 1 as f32);
+ println!("{}", 1 as f64);
+
+ println!("{}", 1u as int);
+ println!("{}", 1u as uint);
+ println!("{}", 1u as *libc::FILE);
+ println!("{}", 1u as i8);
+ println!("{}", 1u as i16);
+ println!("{}", 1u as i32);
+ println!("{}", 1u as i64);
+ println!("{}", 1u as u8);
+ println!("{}", 1u as u16);
+ println!("{}", 1u as u32);
+ println!("{}", 1u as u64);
+ println!("{}", 1u as f32);
+ println!("{}", 1u as f64);
+
+ println!("{}", 1i8 as int);
+ println!("{}", 1i8 as uint);
+ println!("{}", 1i8 as *libc::FILE);
+ println!("{}", 1i8 as i8);
+ println!("{}", 1i8 as i16);
+ println!("{}", 1i8 as i32);
+ println!("{}", 1i8 as i64);
+ println!("{}", 1i8 as u8);
+ println!("{}", 1i8 as u16);
+ println!("{}", 1i8 as u32);
+ println!("{}", 1i8 as u64);
+ println!("{}", 1i8 as f32);
+ println!("{}", 1i8 as f64);
+
+ println!("{}", 1u8 as int);
+ println!("{}", 1u8 as uint);
+ println!("{}", 1u8 as *libc::FILE);
+ println!("{}", 1u8 as i8);
+ println!("{}", 1u8 as i16);
+ println!("{}", 1u8 as i32);
+ println!("{}", 1u8 as i64);
+ println!("{}", 1u8 as u8);
+ println!("{}", 1u8 as u16);
+ println!("{}", 1u8 as u32);
+ println!("{}", 1u8 as u64);
+ println!("{}", 1u8 as f32);
+ println!("{}", 1u8 as f64);
+
+ println!("{}", 1i16 as int);
+ println!("{}", 1i16 as uint);
+ println!("{}", 1i16 as *libc::FILE);
+ println!("{}", 1i16 as i8);
+ println!("{}", 1i16 as i16);
+ println!("{}", 1i16 as i32);
+ println!("{}", 1i16 as i64);
+ println!("{}", 1i16 as u8);
+ println!("{}", 1i16 as u16);
+ println!("{}", 1i16 as u32);
+ println!("{}", 1i16 as u64);
+ println!("{}", 1i16 as f32);
+ println!("{}", 1i16 as f64);
+
+ println!("{}", 1u16 as int);
+ println!("{}", 1u16 as uint);
+ println!("{}", 1u16 as *libc::FILE);
+ println!("{}", 1u16 as i8);
+ println!("{}", 1u16 as i16);
+ println!("{}", 1u16 as i32);
+ println!("{}", 1u16 as i64);
+ println!("{}", 1u16 as u8);
+ println!("{}", 1u16 as u16);
+ println!("{}", 1u16 as u32);
+ println!("{}", 1u16 as u64);
+ println!("{}", 1u16 as f32);
+ println!("{}", 1u16 as f64);
+
+ println!("{}", 1i32 as int);
+ println!("{}", 1i32 as uint);
+ println!("{}", 1i32 as *libc::FILE);
+ println!("{}", 1i32 as i8);
+ println!("{}", 1i32 as i16);
+ println!("{}", 1i32 as i32);
+ println!("{}", 1i32 as i64);
+ println!("{}", 1i32 as u8);
+ println!("{}", 1i32 as u16);
+ println!("{}", 1i32 as u32);
+ println!("{}", 1i32 as u64);
+ println!("{}", 1i32 as f32);
+ println!("{}", 1i32 as f64);
+
+ println!("{}", 1u32 as int);
+ println!("{}", 1u32 as uint);
+ println!("{}", 1u32 as *libc::FILE);
+ println!("{}", 1u32 as i8);
+ println!("{}", 1u32 as i16);
+ println!("{}", 1u32 as i32);
+ println!("{}", 1u32 as i64);
+ println!("{}", 1u32 as u8);
+ println!("{}", 1u32 as u16);
+ println!("{}", 1u32 as u32);
+ println!("{}", 1u32 as u64);
+ println!("{}", 1u32 as f32);
+ println!("{}", 1u32 as f64);
+
+ println!("{}", 1i64 as int);
+ println!("{}", 1i64 as uint);
+ println!("{}", 1i64 as *libc::FILE);
+ println!("{}", 1i64 as i8);
+ println!("{}", 1i64 as i16);
+ println!("{}", 1i64 as i32);
+ println!("{}", 1i64 as i64);
+ println!("{}", 1i64 as u8);
+ println!("{}", 1i64 as u16);
+ println!("{}", 1i64 as u32);
+ println!("{}", 1i64 as u64);
+ println!("{}", 1i64 as f32);
+ println!("{}", 1i64 as f64);
+
+ println!("{}", 1u64 as int);
+ println!("{}", 1u64 as uint);
+ println!("{}", 1u64 as *libc::FILE);
+ println!("{}", 1u64 as i8);
+ println!("{}", 1u64 as i16);
+ println!("{}", 1u64 as i32);
+ println!("{}", 1u64 as i64);
+ println!("{}", 1u64 as u8);
+ println!("{}", 1u64 as u16);
+ println!("{}", 1u64 as u32);
+ println!("{}", 1u64 as u64);
+ println!("{}", 1u64 as f32);
+ println!("{}", 1u64 as f64);
+
+ println!("{}", 1u64 as int);
+ println!("{}", 1u64 as uint);
+ println!("{}", 1u64 as *libc::FILE);
+ println!("{}", 1u64 as i8);
+ println!("{}", 1u64 as i16);
+ println!("{}", 1u64 as i32);
+ println!("{}", 1u64 as i64);
+ println!("{}", 1u64 as u8);
+ println!("{}", 1u64 as u16);
+ println!("{}", 1u64 as u32);
+ println!("{}", 1u64 as u64);
+ println!("{}", 1u64 as f32);
+ println!("{}", 1u64 as f64);
+
+ println!("{}", true as int);
+ println!("{}", true as uint);
+ println!("{}", true as *libc::FILE);
+ println!("{}", true as i8);
+ println!("{}", true as i16);
+ println!("{}", true as i32);
+ println!("{}", true as i64);
+ println!("{}", true as u8);
+ println!("{}", true as u16);
+ println!("{}", true as u32);
+ println!("{}", true as u64);
+ println!("{}", true as f32);
+ println!("{}", true as f64);
+
+ println!("{}", 1. as int);
+ println!("{}", 1. as uint);
+ println!("{}", 1. as i8);
+ println!("{}", 1. as i16);
+ println!("{}", 1. as i32);
+ println!("{}", 1. as i64);
+ println!("{}", 1. as u8);
+ println!("{}", 1. as u16);
+ println!("{}", 1. as u32);
+ println!("{}", 1. as u64);
+ println!("{}", 1. as f32);
+ println!("{}", 1. as f64);
+
+ println!("{}", 1f32 as int);
+ println!("{}", 1f32 as uint);
+ println!("{}", 1f32 as i8);
+ println!("{}", 1f32 as i16);
+ println!("{}", 1f32 as i32);
+ println!("{}", 1f32 as i64);
+ println!("{}", 1f32 as u8);
+ println!("{}", 1f32 as u16);
+ println!("{}", 1f32 as u32);
+ println!("{}", 1f32 as u64);
+ println!("{}", 1f32 as f32);
+ println!("{}", 1f32 as f64);
+
+ println!("{}", 1f64 as int);
+ println!("{}", 1f64 as uint);
+ println!("{}", 1f64 as i8);
+ println!("{}", 1f64 as i16);
+ println!("{}", 1f64 as i32);
+ println!("{}", 1f64 as i64);
+ println!("{}", 1f64 as u8);
+ println!("{}", 1f64 as u16);
+ println!("{}", 1f64 as u32);
+ println!("{}", 1f64 as u64);
+ println!("{}", 1f64 as f32);
+ println!("{}", 1f64 as f64);
}
pub fn main() {
let x = t_rec {c8: 22u8, t: a_tag(44u64)};
let y = format!("{:?}", x);
- info!("y = {}", y);
+ println!("y = {}", y);
assert_eq!(y, ~"t_rec{c8: 22u8, t: a_tag(44u64)}");
}
pub fn main() { let k = checktrue; evenk(42, k); oddk(45, k); }
fn evenk(n: int, k: fn(bool) -> bool) -> bool {
- info!("evenk");
- info!("{:?}", n);
+ println!("evenk");
+ println!("{:?}", n);
if n == 0 { return k(true); } else { return oddk(n - 1, k); }
}
fn oddk(n: int, k: fn(bool) -> bool) -> bool {
- info!("oddk");
- info!("{:?}", n);
+ println!("oddk");
+ println!("{:?}", n);
if n == 0 { return k(false); } else { return evenk(n - 1, k); }
}
// ignore-fast
-extern crate extra;
-
use std::task;
pub fn main() { test05(); }
fn test05_start(tx : &Sender<int>) {
tx.send(10);
- error!("sent 10");
+ println!("sent 10");
tx.send(20);
- error!("sent 20");
+ println!("sent 20");
tx.send(30);
- error!("sent 30");
+ println!("sent 30");
}
fn test05() {
let (tx, rx) = channel();
task::spawn(proc() { test05_start(&tx) });
let mut value: int = rx.recv();
- error!("{}", value);
+ println!("{}", value);
value = rx.recv();
- error!("{}", value);
+ println!("{}", value);
value = rx.recv();
- error!("{}", value);
+ println!("{}", value);
assert_eq!(value, 30);
}
pub fn main() { test00(); }
-fn start() { info!("Started / Finished task."); }
+fn start() { println!("Started / Finished task."); }
fn test00() {
task::try(proc() start() );
- info!("Completing.");
+ println!("Completing.");
}
// ignore-fast
-extern crate extra;
-
use std::task;
fn start(tx: &Sender<Sender<~str>>) {
let mut b;
a = rx.recv();
assert!(a == ~"A");
- error!("{:?}", a);
+ println!("{:?}", a);
b = rx.recv();
assert!(b == ~"B");
- error!("{:?}", b);
+ println!("{:?}", b);
}
pub fn main() {
// ignore-fast
-extern crate extra;
-
use std::task;
fn start(tx: &Sender<Sender<int>>) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::task;
pub fn main() { test00(); }
-fn start(_task_number: int) { info!("Started / Finished task."); }
+fn start(_task_number: int) { println!("Started / Finished task."); }
fn test00() {
let i: int = 0;
// Try joining tasks that have already finished.
result.recv();
- info!("Joined task.");
+ println!("Joined task.");
}
// ignore-fast
-extern crate extra;
-
use std::task;
fn start(tx: &Sender<int>, start: int, number_of_messages: int) {
}
pub fn main() {
- info!("Check that we don't deadlock.");
+ println!("Check that we don't deadlock.");
let (tx, rx) = channel();
task::try(proc() { start(&tx, 0, 10) });
- info!("Joined task");
+ println!("Joined task");
}
// Spawn 10 tasks each sending us back one int.
let mut i = 10;
while (i > 0) {
- info!("{}", i);
+ println!("{}", i);
let tx = tx.clone();
task::spawn({let i = i; proc() { child(i, &tx) }});
i = i - 1;
i = 10;
while (i > 0) {
- info!("{}", i);
+ println!("{}", i);
rx.recv();
i = i - 1;
}
- info!("main thread exiting");
+ println!("main thread exiting");
}
fn child(x: int, tx: &Sender<int>) {
- info!("{}", x);
+ println!("{}", x);
tx.send(x);
}
// ignore-fast
-extern crate extra;
-
use std::task;
fn start(tx: &Sender<int>, i0: int) {
// This test is specifically about spawning temporary closures.
-extern crate extra;
-
use std::task;
fn f() {
// ignore-fast
-extern crate extra;
-
use std::task;
-pub fn main() { info!("===== WITHOUT THREADS ====="); test00(); }
+pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); }
fn test00_start(ch: &Sender<int>, message: int, count: int) {
- info!("Starting test00_start");
+ println!("Starting test00_start");
let mut i: int = 0;
while i < count {
- info!("Sending Message");
+ println!("Sending Message");
ch.send(message + 0);
i = i + 1;
}
- info!("Ending test00_start");
+ println!("Ending test00_start");
}
fn test00() {
let number_of_tasks: int = 16;
let number_of_messages: int = 4;
- info!("Creating tasks");
+ println!("Creating tasks");
let (tx, rx) = channel();
// Join spawned tasks...
for r in results.iter() { r.recv(); }
- info!("Completed: Final number is: ");
- error!("{:?}", sum);
+ println!("Completed: Final number is: ");
+ println!("{:?}", sum);
// assert (sum == (((number_of_tasks * (number_of_tasks - 1)) / 2) *
// number_of_messages));
assert_eq!(sum, 480);
tx.send(4);
r = rx.recv();
sum += r;
- info!("{}", r);
+ println!("{}", r);
r = rx.recv();
sum += r;
- info!("{}", r);
+ println!("{}", r);
r = rx.recv();
sum += r;
- info!("{}", r);
+ println!("{}", r);
r = rx.recv();
sum += r;
- info!("{}", r);
+ println!("{}", r);
tx.send(5);
tx.send(6);
tx.send(7);
tx.send(8);
r = rx.recv();
sum += r;
- info!("{}", r);
+ println!("{}", r);
r = rx.recv();
sum += r;
- info!("{}", r);
+ println!("{}", r);
r = rx.recv();
sum += r;
- info!("{}", r);
+ println!("{}", r);
r = rx.recv();
sum += r;
- info!("{}", r);
+ println!("{}", r);
assert_eq!(sum, 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
pub fn main() { test00(); }
fn test00() {
#[allow(dead_assignment)];
-extern crate extra;
-
use std::task;
pub fn main() { test00(); }
// ignore-fast
-extern crate extra;
-
use std::task;
pub fn main() { test00(); }
let mut i: int = 0;
while i < number_of_messages {
sum += rx.recv();
- info!("{:?}", r);
+ println!("{:?}", r);
i += 1;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-extern crate extra;
-
// rustboot can't transmit nils across channels because they don't have
// any size, but rustc currently can because they do have size. Whether
// or not this is desirable I don't know, but here's a regression test.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::task;
pub fn main() {
// ignore-android needs extra network permissions
// exec-env:RUST_LOG=debug
+#[feature(phase)];
+#[phase(syntax, link)]
+extern crate log;
+
use std::libc;
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::io::net::tcp::{TcpListener, TcpStream};
});
let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 0 };
- let (p, c) = Chan::new();
+ let (tx, rx) = channel();
spawn(proc() {
let mut listener = TcpListener::bind(addr).unwrap();
- c.send(listener.socket_name().unwrap());
+ tx.send(listener.socket_name().unwrap());
let mut acceptor = listener.listen();
loop {
let mut stream = match acceptor.accept() {
stream.write([2]);
}
});
- let addr = p.recv();
+ let addr = rx.recv();
- let (p, c) = Chan::new();
+ let (tx, rx) = channel();
for _ in range(0, 1000) {
- let c = c.clone();
+ let tx = tx.clone();
spawn(proc() {
match TcpStream::connect(addr) {
Ok(stream) => {
},
Err(e) => debug!("{:?}", e)
}
- c.send(());
+ tx.send(());
});
}
// Wait for all clients to exit, but don't wait for the server to exit. The
// server just runs infinitely.
- drop(c);
+ drop(tx);
for _ in range(0, 1000) {
- p.recv();
+ rx.recv();
}
unsafe { libc::exit(0) }
}
// they're in a different location than before. Hence, these tests are all run
// serially here.
-extern crate extra;
-
-use extra::tempfile::TempDir;
-use std::io::fs;
+use std::io::{fs, TempDir};
use std::io;
use std::os;
use std::task;
fn recursive_mkdir_rel() {
let path = Path::new("frob");
let cwd = os::getcwd();
- debug!("recursive_mkdir_rel: Making: {} in cwd {} [{:?}]", path.display(),
+ println!("recursive_mkdir_rel: Making: {} in cwd {} [{:?}]", path.display(),
cwd.display(), path.exists());
fs::mkdir_recursive(&path, io::UserRWX);
assert!(path.is_dir());
fn recursive_mkdir_rel_2() {
let path = Path::new("./frob/baz");
let cwd = os::getcwd();
- debug!("recursive_mkdir_rel_2: Making: {} in cwd {} [{:?}]", path.display(),
+ println!("recursive_mkdir_rel_2: Making: {} in cwd {} [{:?}]", path.display(),
cwd.display(), path.exists());
fs::mkdir_recursive(&path, io::UserRWX);
assert!(path.is_dir());
assert!(path.dir_path().is_dir());
let path2 = Path::new("quux/blat");
- debug!("recursive_mkdir_rel_2: Making: {} in cwd {}", path2.display(),
+ println!("recursive_mkdir_rel_2: Making: {} in cwd {}", path2.display(),
cwd.display());
fs::mkdir_recursive(&path2, io::UserRWX);
assert!(path2.is_dir());
let tmpdir = tmpdir.path();
let root = tmpdir.join("foo");
- debug!("making {}", root.display());
+ println!("making {}", root.display());
fs::mkdir(&root, rwx);
fs::mkdir(&root.join("foo"), rwx);
fs::mkdir(&root.join("foo").join("bar"), rwx);
// Issue #787
// Don't try to clean up uninitialized locals
-extern crate extra;
-
use std::task;
fn test_break() { loop { let _x: @int = break; } }
// compile-flags: --test --cfg ignorecfg
// ignore-fast
-extern crate extra;
-
#[test]
#[ignore(cfg(ignorecfg))]
fn shouldignore() {
// ignore-fast
// ignore-win32 #10872
-extern crate extra;
-
// Building as a test runner means that a synthetic main will be run,
// not ours
pub fn main() { fail!(); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::task;
pub fn main() {
let mut i = 10;
while i > 0 { task::spawn({let i = i; proc() child(i)}); i = i - 1; }
- info!("main thread exiting");
+ println!("main thread exiting");
}
-fn child(x: int) { info!("{}", x); }
+fn child(x: int) { println!("{}", x); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::cmp::{Eq, Ord};
use std::num::NumCast;
// A more complex example of numeric extensions
-extern crate extra;
-
use std::cmp::{Eq, Ord};
pub trait TypeExt {}
let (tx, rx) = channel();
tx.send(42);
let r = rx.recv();
- error!("{:?}", r);
+ println!("{:?}", r);
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test checks that the `_` type placeholder works
+// correctly for enabling type inference.
+
+static CONSTEXPR: *int = &'static 413 as *_;
+
+pub fn main() {
+ use std::vec_ng::Vec;
+
+ let x: Vec<_> = range(0u, 5).collect();
+ assert_eq!(x.as_slice(), &[0u,1,2,3,4]);
+
+ let x = range(0u, 5).collect::<Vec<_>>();
+ assert_eq!(x.as_slice(), &[0u,1,2,3,4]);
+
+ let y: _ = "hello";
+ assert_eq!(y.len(), 5);
+
+ let ptr = &5u;
+ let ptr2 = ptr as *_;
+
+ assert_eq!(ptr as *uint as uint, ptr2 as uint);
+}
assert!(!Equal::isEq(branch(@leaf(magenta), @leaf(cyan)),
branch(@leaf(magenta), @leaf(magenta))));
- error!("Assertions all succeeded!");
+ println!("Assertions all succeeded!");
}
assert!(!branch(@leaf(magenta), @leaf(cyan))
.isEq(branch(@leaf(magenta), @leaf(magenta))));
- error!("Assertions all succeeded!");
+ println!("Assertions all succeeded!");
}
pub fn main() {
let a = 1;
let a_neg: i8 = -a;
- error!("{}", a_neg);
+ println!("{}", a_neg);
let b = 1;
let b_neg: i16 = -b;
- error!("{}", b_neg);
+ println!("{}", b_neg);
let c = 1;
let c_neg: i32 = -c;
- error!("{}", c_neg);
+ println!("{}", c_neg);
let d = 1;
let d_neg: i64 = -d;
- error!("{}", d_neg);
+ println!("{}", d_neg);
let e = 1;
let e_neg: int = -e;
- error!("{}", e_neg);
+ println!("{}", e_neg);
// intentional overflows
let f = 1;
let f_neg: u8 = -f;
- error!("{}", f_neg);
+ println!("{}", f_neg);
let g = 1;
let g_neg: u16 = -g;
- error!("{}", g_neg);
+ println!("{}", g_neg);
let h = 1;
let h_neg: u32 = -h;
- error!("{}", h_neg);
+ println!("{}", h_neg);
let i = 1;
let i_neg: u64 = -i;
- error!("{}", i_neg);
+ println!("{}", i_neg);
let j = 1;
let j_neg: uint = -j;
- error!("{}", j_neg);
+ println!("{}", j_neg);
}
// Tests that the tail expr in null() has its type
// unified with the type *T, and so the type variable
// in that type gets resolved.
-extern crate extra;
use std::cast;
let rc1 = managed::refcount(*i);
let j = i.clone();
let rc2 = managed::refcount(*i);
- error!("rc1: {} rc2: {}", rc1, rc2);
+ println!("rc1: {} rc2: {}", rc1, rc2);
assert_eq!(rc1 + 1u, rc2);
}
let x = u(~10);
assert!(match x {
u(a) => {
- error!("{:?}", a);
+ println!("{:?}", a);
*a
}
_ => { 66 }
pub fn main() {
let i = ~100;
- error!("{:?}", i);
+ println!("{:?}", i);
}
pub fn main() {
assert!(match u(~10) {
u(a) => {
- error!("{:?}", a);
+ println!("{:?}", a);
*a
}
_ => { 66 }
#[feature(managed_boxes)];
-extern crate extra;
-
use std::task;
fn f() {
// ignore-fast
-extern crate extra;
-
use std::task;
struct complainer {
impl Drop for complainer {
fn drop(&mut self) {
- error!("About to send!");
+ println!("About to send!");
self.tx.send(true);
- error!("Sent!");
+ println!("Sent!");
}
}
fn complainer(tx: Sender<bool>) -> complainer {
- error!("Hello!");
+ println!("Hello!");
complainer {
tx: tx
}
pub fn main() {
let (tx, rx) = channel();
task::spawn(proc() f(tx.clone()));
- error!("hiiiiiiiii");
+ println!("hiiiiiiiii");
assert!(rx.recv());
}
#[feature(managed_boxes)];
-extern crate extra;
-
use std::task;
struct complainer {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::task;
fn f() {
// except according to those terms.
// Issue #1706
-extern crate stdlib = "extra";
+extern crate stdlib = "std";
pub fn main() {}
enum myoption<T> { none, some(T), }
-pub fn main() { info!("{}", 5); }
+pub fn main() { println!("{}", 5); }
enum myoption<T> { none, some(T), }
-pub fn main() { info!("{}", 5); }
+pub fn main() { println!("{}", 5); }
fn check_str_eq(a: ~str, b: ~str) {
let mut i: int = 0;
for ab in a.bytes() {
- info!("{}", i);
- info!("{}", ab);
+ println!("{}", i);
+ println!("{}", ab);
let bb: u8 = b[i];
- info!("{}", bb);
+ println!("{}", bb);
assert_eq!(ab, bb);
i += 1;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
use std::str;
pub fn main() {
let a: ~[int] = ~[1, 2, 3, 4, 5];
let b: ~[int] = ~[6, 7, 8, 9, 0];
let v: ~[int] = a + b;
- info!("{}", v[9]);
+ println!("{}", v[9]);
assert_eq!(v[0], 1);
assert_eq!(v[7], 8);
assert_eq!(v[9], 0);
pub fn main() {
let mut later: ~[int];
if true { later = ~[1]; } else { later = ~[2]; }
- info!("{}", later[0]);
+ println!("{}", later[0]);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-extern crate extra;
-
fn test_heap_to_heap() {
// a spills onto the heap
let mut a = ~[0, 1, 2, 3, 4];
let mut i = 20;
let mut expected_len = 1u;
while i > 0 {
- error!("{}", a.len());
+ println!("{}", a.len());
assert_eq!(a.len(), expected_len);
a = a + a; // FIXME(#3387)---can't write a += a
i -= 1;
fn p() -> bool { true }
let _a = (assert!((true)) == (assert!(p())));
let _c = (assert!((p())) == ());
- let _b: bool = (info!("{}", 0) == (return 0u));
+ let _b: bool = (println!("{}", 0) == (return 0u));
}
fn angrydome() {
break; }
}
-fn evil_lincoln() { let _evil = info!("lincoln"); }
+fn evil_lincoln() { let _evil = println!("lincoln"); }
pub fn main() {
strange();
let mut i = 1;
while i > 0 {
assert!((i > 0));
- info!("{}", i);
+ println!("{}", i);
i -= 1;
continue;
}
while z < 50 {
z += 1;
while false { x = y; y = z; }
- info!("{}", y);
+ println!("{}", y);
}
assert!((y == 42 && z == 50));
}
pub fn main() {
let mut i: int = 90;
while i < 100 {
- info!("{}", i);
+ println!("{}", i);
i = i + 1;
if i == 95 {
let _v: ~[int] =
~[1, 2, 3, 4, 5]; // we check that it is freed by break
- info!("breaking");
+ println!("breaking");
break;
}
}
pub fn main() {
let mut x: int = 10;
let mut y: int = 0;
- while y < x { info!("{}", y); info!("hello"); y = y + 1; }
+ while y < x { println!("{}", y); println!("hello"); y = y + 1; }
while x > 0 {
- info!("goodbye");
+ println!("goodbye");
x = x - 1;
- info!("{}", x);
+ println!("{}", x);
}
}
let expected = 1234u;
kernel32::SetLastError(expected);
let actual = kernel32::GetLastError();
- info!("actual = {}", actual);
+ println!("actual = {}", actual);
assert_eq!(expected, actual);
}
}
let mut builder = task::task();
let mut result = builder.future_result();
builder.spawn(child);
- error!("1");
+ println!("1");
task::deschedule();
- error!("2");
+ println!("2");
task::deschedule();
- error!("3");
+ println!("3");
result.recv();
}
fn child() {
- error!("4"); task::deschedule(); error!("5"); task::deschedule(); error!("6");
+ println!("4"); task::deschedule(); println!("5"); task::deschedule(); println!("6");
}
let mut builder = task::task();
let mut result = builder.future_result();
builder.spawn(child);
- error!("1");
+ println!("1");
task::deschedule();
result.recv();
}
-fn child() { error!("2"); }
+fn child() { println!("2"); }
pub fn main() {
let mut i: int = 0;
- while i < 100 { i = i + 1; error!("{}", i); task::deschedule(); }
+ while i < 100 { i = i + 1; println!("{}", i); task::deschedule(); }
}