This change makes internal compile errors in the compile-fail tests failures.
I believe this is the correct behaviour- those tests are intended to assert that the compiler doesn't proceed, not that it explodes.
So far, it fails on 4 tests in my environment, my testcase for #13943 which is what caused me to tackle this, and 3 others:
```
failures:
[compile-fail] compile-fail/incompatible-tuple.rs # This one is mine and not on master
[compile-fail] compile-fail/inherit-struct8.rs
[compile-fail] compile-fail/issue-9725.rs
[compile-fail] compile-fail/unsupported-cast.rs
```
[submodule "src/compiler-rt"]
path = src/compiler-rt
url = https://github.com/rust-lang/compiler-rt.git
+[submodule "src/rt/hoedown"]
+ path = src/rt/hoedown
+ url = https://github.com/rust-lang/hoedown.git
reedlepee <reedlepee123@gmail.com>
Reuben Morais <reuben.morais@gmail.com>
Richard Diamond <wichard@vitalitystudios.com>
+Richo Healey <richo@psych0tik.net>
Rick Waldron <waldron.rick@gmail.com>
Rob Arnold <robarnold@cs.cmu.edu>
Rob Hoelz <rob@hoelz.ro>
# DEPS_<crate>
# These lists are the dependencies of the <crate> that is to be built.
# Rust dependencies are listed bare (i.e. std, green) and native
-# dependencies have a "native:" prefix (i.e. native:sundown). All deps
+# dependencies have a "native:" prefix (i.e. native:hoedown). All deps
# will be built before the crate itself is built.
#
# TOOL_DEPS_<tool>/TOOL_SOURCE_<tool>
DEPS_syntax := std term serialize collections log
DEPS_rustc := syntax native:rustllvm flate arena serialize sync getopts \
collections time log
-DEPS_rustdoc := rustc native:sundown serialize sync getopts collections \
+DEPS_rustdoc := rustc native:hoedown serialize sync getopts collections \
test time
DEPS_flate := std native:miniz
DEPS_arena := std collections
PKG_TAR = dist/$(PKG_NAME).tar.gz
-PKG_GITMODULES := $(S)src/libuv $(S)src/llvm $(S)src/gyp $(S)src/compiler-rt
+PKG_GITMODULES := $(S)src/libuv $(S)src/llvm $(S)src/gyp $(S)src/compiler-rt \
+ $(S)src/rt/hoedown
PKG_FILES := \
$(S)COPYRIGHT \
$(S)LICENSE-APACHE \
@$(call E, cp: $@)
$(Q)cp -a $< $@ 2> /dev/null
-doc/FiraSans-Regular.woff: $(D)/FiraSans-Regular.woff | doc/
- @$(call E, cp: $@)
- $(Q)cp -a $< $@ 2> /dev/null
-
-doc/FiraSans-Medium.woff: $(D)/FiraSans-Medium.woff | doc/
- @$(call E, cp: $@)
- $(Q)cp -a $< $@ 2> /dev/null
-
-doc/Heuristica-Regular.woff: $(D)/Heuristica-Regular.woff | doc/
- @$(call E, cp: $@)
- $(Q)cp -a $< $@ 2> /dev/null
-
-doc/Heuristica-Italic.woff: $(D)/Heuristica-Italic.woff | doc/
- @$(call E, cp: $@)
- $(Q)cp -a $< $@ 2> /dev/null
-
-doc/Heuristica-Bold.woff: $(D)/Heuristica-Bold.woff | doc/
- @$(call E, cp: $@)
- $(Q)cp -a $< $@ 2> /dev/null
-
# The (english) documentation for each doc item.
define DEF_SHOULD_BUILD_PDF_DOC
CFG_LDPATH_arm-unknown-linux-gnueabihf :=
CFG_RUN_arm-unknown-linux-gnueabihf=$(2)
CFG_RUN_TARG_arm-unknown-linux-gnueabihf=$(call CFG_RUN_arm-unknown-linux-gnueabihf,,$(2))
-RUSTC_FLAGS_arm-unknown-linux-gnueabihf := -C target-feature=+v7,+vfp3
+RUSTC_FLAGS_arm-unknown-linux-gnueabihf := -C target-feature=+v6,+vfp2
RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabihf :=
# arm-unknown-linux-gnueabi configuration
# that's per-target so you're allowed to conditionally add files based on the
# target.
################################################################################
-NATIVE_LIBS := rustrt sundown uv_support morestack miniz context_switch
+NATIVE_LIBS := rustrt hoedown uv_support morestack miniz context_switch
# $(1) is the target triple
define NATIVE_LIBRARIES
-NATIVE_DEPS_sundown_$(1) := sundown/src/autolink.c \
- sundown/src/buffer.c \
- sundown/src/stack.c \
- sundown/src/markdown.c \
- sundown/html/houdini_href_e.c \
- sundown/html/houdini_html_e.c \
- sundown/html/html_smartypants.c \
- sundown/html/html.c
+NATIVE_DEPS_hoedown_$(1) := hoedown/src/autolink.c \
+ hoedown/src/buffer.c \
+ hoedown/src/document.c \
+ hoedown/src/escape.c \
+ hoedown/src/html.c \
+ hoedown/src/html_blocks.c \
+ hoedown/src/html_smartypants.c \
+ hoedown/src/stack.c \
+ hoedown/src/version.c
NATIVE_DEPS_uv_support_$(1) := rust_uv.c
NATIVE_DEPS_miniz_$(1) = miniz.c
NATIVE_DEPS_rustrt_$(1) := rust_builtin.c \
@mkdir -p $$(@D)
@$$(call E, compile: $$@)
$$(Q)$$(call CFG_COMPILE_C_$(1), $$@, \
- -I $$(S)src/rt/sundown/src -I $$(S)src/rt/sundown/html \
+ -I $$(S)src/rt/hoedown/src \
-I $$(S)src/libuv/include -I $$(S)src/rt \
$$(RUNTIME_CFLAGS_$(1))) $$<
$(S)src/rt/*/*/*.cpp \
$(S)src/rustllvm/*.cpp)
ALL_CS := $(filter-out $(S)src/rt/miniz.cpp \
- $(wildcard $(S)src/rt/sundown/src/*.c) \
- $(wildcard $(S)src/rt/sundown/html/*.c) \
+ $(wildcard $(S)src/rt/hoedown/src/*.c) \
+ $(wildcard $(S)src/rt/hoedown/bin/*.c) \
,$(ALL_CS))
ALL_HS := $(wildcard $(S)src/rt/*.h \
$(S)src/rt/*/*.h \
$(S)src/rt/msvc/typeof.h \
$(S)src/rt/msvc/stdint.h \
$(S)src/rt/msvc/inttypes.h \
- $(wildcard $(S)src/rt/sundown/src/*.h) \
- $(wildcard $(S)src/rt/sundown/html/*.h) \
+ $(wildcard $(S)src/rt/hoedown/src/*.h) \
+ $(wildcard $(S)src/rt/hoedown/bin/*.h) \
,$(ALL_HS))
# Run the tidy script in multiple parts to avoid huge 'echo' commands
-and -not -name '*.sh' \
| grep '^$(S)src/llvm' -v \
| grep '^$(S)src/libuv' -v \
+ | grep '^$(S)src/rt/hoedown' -v \
| grep '^$(S)src/gyp' -v \
| grep '^$(S)src/etc' -v \
| grep '^$(S)src/doc' -v \
let x: Option<~str> = str::from_utf8_owned(~[104u8,105u8]);
let y: ~str = x.unwrap();
-~~~~
+~~~
To return a [`MaybeOwned`](http://static.rust-lang.org/doc/master/std/str/enum.MaybeOwned.html) use the str helper function [`from_utf8_lossy`](http://static.rust-lang.org/doc/master/std/str/fn.from_utf8_owned.html). This function also replaces non-valid utf-8 sequences with U+FFFD replacement character.
let x = bytes!(72u8,"ello ",0xF0,0x90,0x80,"World!");
let y = str::from_utf8_lossy(x);
-~~~~
+~~~
# File operations
**Short answer** set the RUST_LOG environment variable to the name of your source file, sans extension.
-``` {.sh .notrust}
+```notrust,sh
rustc hello.rs
export RUST_LOG=hello
./hello
Some(0)
}
}
-~~~~
+~~~
Reaching the end of the iterator is signalled by returning `None` instead of
`Some(item)`:
The following is a minimal example of calling a foreign function which will
compile if snappy is installed:
-~~~~
+~~~~no_run
extern crate libc;
use libc::size_t;
#[link(name = "snappy")]
-# #[cfg(ignore_this)]
extern {
fn snappy_max_compressed_length(source_length: size_t) -> size_t;
}
-# unsafe fn snappy_max_compressed_length(a: size_t) -> size_t { a }
fn main() {
let x = unsafe { snappy_max_compressed_length(100) };
The `extern` block can be extended to cover the entire snappy API:
-~~~~ {.ignore}
+~~~~no_run
extern crate libc;
use libc::{c_int, size_t};
fn snappy_validate_compressed_buffer(compressed: *u8,
compressed_length: size_t) -> c_int;
}
+# fn main() {}
~~~~
# Creating a safe interface
Rust code:
-~~~~
+~~~~no_run
extern fn callback(a:i32) {
println!("I'm called from C with value {0}", a);
}
#[link(name = "extlib")]
-# #[cfg(ignore)]
extern {
fn register_callback(cb: extern fn(i32)) -> i32;
fn trigger_callback();
}
-# unsafe fn register_callback(cb: extern fn(i32)) -> i32 { 0 }
-# unsafe fn trigger_callback() { }
fn main() {
unsafe {
Rust code:
-~~~~
+~~~~no_run
struct RustObject {
a: i32,
}
#[link(name = "extlib")]
-# #[cfg(ignore)]
extern {
fn register_callback(target: *mut RustObject,
cb: extern fn(*mut RustObject, i32)) -> i32;
fn trigger_callback();
}
-# unsafe fn register_callback(a: *mut RustObject,
-# b: extern fn(*mut RustObject, i32)) -> i32 { 0 }
-# unsafe fn trigger_callback() {}
fn main() {
// Create the object that will be referenced in the callback
- let mut rust_object = ~RustObject{ a: 5 };
+ let mut rust_object = box RustObject { a: 5 };
unsafe {
register_callback(&mut *rust_object, callback);
specifies raw flags which need to get passed to the linker when producing an
artifact. An example usage would be:
-~~~ {.ignore}
+~~~ no_run
+#![feature(link_args)]
+
#[link_args = "-foo -bar -baz"]
extern {}
+# fn main() {}
~~~
Note that this feature is currently hidden behind the `feature(link_args)` gate
global state. In order to access these variables, you declare them in `extern`
blocks with the `static` keyword:
-~~~
+~~~no_run
extern crate libc;
#[link(name = "readline")]
-# #[cfg(ignore)]
extern {
static rl_readline_version: libc::c_int;
}
-# static rl_readline_version: libc::c_int = 0;
fn main() {
println!("You have readline version {} installed.",
interface. To do this, statics can be declared with `mut` so rust can mutate
them.
-~~~
+~~~no_run
extern crate libc;
use std::ptr;
#[link(name = "readline")]
-# #[cfg(ignore)]
extern {
static mut rl_prompt: *libc::c_char;
}
-# static mut rl_prompt: *libc::c_char = 0 as *libc::c_char;
fn main() {
"[my-awesome-shell] $".with_c_str(|buf| {
extern "stdcall" {
fn SetEnvironmentVariableA(n: *u8, v: *u8) -> libc::c_int;
}
-
# fn main() { }
~~~~
~~~
# struct Point {x: f64, y: f64}
-let on_the_stack : Point = Point {x: 3.0, y: 4.0};
-let managed_box : @Point = @Point {x: 5.0, y: 1.0};
-let owned_box : ~Point = ~Point {x: 7.0, y: 9.0};
+let on_the_stack : Point = Point {x: 3.0, y: 4.0};
+let managed_box : @Point = @Point {x: 5.0, y: 1.0};
+let owned_box : Box<Point> = box Point {x: 7.0, y: 9.0};
~~~
Suppose we wanted to write a procedure that computed the distance between any
~~~
# struct Point {x: f64, y: f64}
-# let on_the_stack : Point = Point{x: 3.0, y: 4.0};
-# let managed_box : @Point = @Point{x: 5.0, y: 1.0};
-# let owned_box : ~Point = ~Point{x: 7.0, y: 9.0};
+# let on_the_stack : Point = Point{x: 3.0, y: 4.0};
+# let managed_box : @Point = @Point{x: 5.0, y: 1.0};
+# let owned_box : Box<Point> = box Point{x: 7.0, y: 9.0};
# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
compute_distance(&on_the_stack, managed_box);
compute_distance(managed_box, owned_box);
# struct Point {x: f64, y: f64}
# struct Size {w: f64, h: f64} // as before
# struct Rectangle {origin: Point, size: Size}
-let rect_stack = &Rectangle {origin: Point {x: 1.0, y: 2.0},
- size: Size {w: 3.0, h: 4.0}};
-let rect_managed = @Rectangle {origin: Point {x: 3.0, y: 4.0},
- size: Size {w: 3.0, h: 4.0}};
-let rect_owned = ~Rectangle {origin: Point {x: 5.0, y: 6.0},
- size: Size {w: 3.0, h: 4.0}};
+let rect_stack = &Rectangle {origin: Point {x: 1.0, y: 2.0},
+ size: Size {w: 3.0, h: 4.0}};
+let rect_managed = @Rectangle {origin: Point {x: 3.0, y: 4.0},
+ size: Size {w: 3.0, h: 4.0}};
+let rect_owned = box Rectangle {origin: Point {x: 5.0, y: 6.0},
+ size: Size {w: 3.0, h: 4.0}};
~~~
In each case, we can extract out individual subcomponents with the `&`
# struct Rectangle {origin: Point, size: Size}
# let rect_stack = &Rectangle {origin: Point {x: 1.0, y: 2.0}, size: Size {w: 3.0, h: 4.0}};
# let rect_managed = @Rectangle {origin: Point {x: 3.0, y: 4.0}, size: Size {w: 3.0, h: 4.0}};
-# let rect_owned = ~Rectangle {origin: Point {x: 5.0, y: 6.0}, size: Size {w: 3.0, h: 4.0}};
+# let rect_owned = box Rectangle {origin: Point {x: 5.0, y: 6.0}, size: Size {w: 3.0, h: 4.0}};
# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
compute_distance(&rect_stack.origin, &rect_managed.origin);
~~~
# fn some_condition() -> bool { true }
# struct Foo { f: int }
fn example3() -> int {
- let mut x = ~Foo {f: 3};
+ let mut x = box Foo {f: 3};
if some_condition() {
let y = &x.f; // -+ L
return *y; // |
} // -+
- x = ~Foo {f: 4};
+ x = box Foo {f: 4};
// ...
# return 0;
}
~~~ {.ignore}
fn example3() -> int {
- let mut x = ~X {f: 3};
+ let mut x = box X {f: 3};
let y = &x.f;
- x = ~X {f: 4}; // Error reported here.
+ x = box X {f: 4}; // Error reported here.
*y
}
~~~
~~~ {.notrust}
Stack Exchange Heap
- x +----------+
- | ~{f:int} | ----+
- y +----------+ |
- | &int | ----+
- +----------+ | +---------+
- +--> | f: 3 |
- +---------+
+ x +-------------+
+ | box {f:int} | ----+
+ y +-------------+ |
+ | &int | ----+
+ +-------------+ | +---------+
+ +--> | f: 3 |
+ +---------+
~~~
Once the reassignment occurs, the memory will look like this:
~~~ {.notrust}
Stack Exchange Heap
- x +----------+ +---------+
- | ~{f:int} | -------> | f: 4 |
- y +----------+ +---------+
- | &int | ----+
- +----------+ | +---------+
- +--> | (freed) |
- +---------+
+ x +-------------+ +---------+
+ | box {f:int} | -------> | f: 4 |
+ y +-------------+ +---------+
+ | &int | ----+
+ +-------------+ | +---------+
+ +--> | (freed) |
+ +---------+
~~~
Here you can see that the variable `y` still points at the old box,
~~~ {.ignore}
fn example3() -> int {
struct R { g: int }
- struct S { f: ~R }
+ struct S { f: Box<R> }
- let mut x = ~S {f: ~R {g: 3}};
+ let mut x = box S {f: box R {g: 3}};
let y = &x.f.g;
- x = ~S {f: ~R {g: 4}}; // Error reported here.
- x.f = ~R {g: 5}; // Error reported here.
+ x = box S {f: box R {g: 4}}; // Error reported here.
+ x.f = box R {g: 5}; // Error reported here.
*y
}
~~~
Sometimes, you need a recursive data structure. The simplest is known as a 'cons list':
~~~rust
+
enum List<T> {
Nil,
- Cons(T, ~List<T>),
+ Cons(T, Box<List<T>>),
}
fn main() {
- let list: List<int> = Cons(1, ~Cons(2, ~Cons(3, ~Nil)));
+ let list: List<int> = Cons(1, box Cons(2, box Cons(3, box Nil)));
println!("{:?}", list);
}
~~~
This prints:
~~~ {.notrust}
-Cons(1, ~Cons(2, ~Cons(3, ~Nil)))
+Cons(1, box Cons(2, box Cons(3, box Nil)))
~~~
The inner lists _must_ be an owned pointer, because we can't know how many
}
fn main() {
- let a = ~Point { x: 10, y: 20 };
+ let a = box Point { x: 10, y: 20 };
spawn(proc() {
println!("{}", a.x);
});
}
fn main() {
- let a = ~Point { x: 10, y: 20 };
+ let a = box Point { x: 10, y: 20 };
let b = a;
println!("{}", b.x);
println!("{}", a.x);
<std-macros>:158:27: 158:81 note: expansion site
<std-macros>:157:5: 159:6 note: in expansion of println!
test.rs:10:5: 10:25 note: expansion site
-test.rs:8:9: 8:10 note: `a` moved here because it has type `~Point`, which is moved by default (use `ref` to override)
+test.rs:8:9: 8:10 note: `a` moved here because it has type `Box<Point>`, which is moved by default (use `ref` to override)
test.rs:8 let b = a;
^
~~~
}
fn main() {
- let origin = @Point { x: 0.0, y: 0.0 };
- let p1 = ~Point { x: 5.0, y: 3.0 };
+ let origin = @Point { x: 0.0, y: 0.0 };
+ let p1 = box Point { x: 5.0, y: 3.0 };
println!("{:?}", compute_distance(origin, p1));
}
~~~rust
fn main() {
- let mut x = ~5;
+ let mut x = box 5;
if *x < 10 {
let y = &x;
println!("Oh no: {:?}", y);
~~~rust{.ignore}
fn main() {
- let mut x = ~5;
+ let mut x = box 5;
if *x < 10 {
let y = &x;
*x -= 1;
What does that mean? Don't do this:
~~~rust
-fn foo(x: ~int) -> ~int {
- return ~*x;
+fn foo(x: Box<int>) -> Box<int> {
+ return box *x;
}
fn main() {
- let x = ~5;
+ let x = box 5;
let y = foo(x);
}
~~~
Do this:
~~~rust
-fn foo(x: ~int) -> int {
+fn foo(x: Box<int>) -> int {
return *x;
}
fn main() {
- let x = ~5;
- let y = ~foo(x);
+ let x = box 5;
+ let y = box foo(x);
}
~~~
also work:
~~~rust
-fn foo(x: ~int) -> int {
+fn foo(x: Box<int>) -> int {
return *x;
}
fn main() {
- let x = ~5;
+ let x = box 5;
let y = @foo(x);
}
~~~
}
}
# }
-~~~~
+~~~
The implementation of `DuplexStream` supports both sending and
receiving. The `stringifier` function takes a `DuplexStream` that can
assert!(from_child.recv() == "0".to_owned());
# }
-~~~~
+~~~
The parent task first calls `DuplexStream` to create a pair of bidirectional
endpoints. It then uses `task::spawn` to create the child task, which captures
}
}
-// A comparison between the built-in ~ and this reimplementation
+// A comparison between the built-in `Box` and this reimplementation
fn main() {
{
- let mut x = ~5;
+ let mut x = box 5;
*x = 10;
} // `x` is freed here
but what about heap memory?
Rust has a second kind of pointer,
an 'owned box',
-that you can create with a `~`.
+that you can create with the `box` operator.
Check it out:
```
-fn dangling() -> ~int {
- let i = ~1234;
+
+fn dangling() -> Box<int> {
+ let i = box 1234;
return i;
}
```
Now instead of a stack allocated `1234`,
-we have a heap allocated `~1234`.
+we have a heap allocated `box 1234`.
Whereas `&` borrows a pointer to existing memory,
creating an owned box allocates memory on the heap and places a value in it,
giving you the sole pointer to that memory.
```
// Rust
-let i = ~1234;
+let i = box 1234;
```
```notrust
Rust input is interpreted as a sequence of Unicode codepoints encoded in UTF-8,
normalized to Unicode normalization form NFKC.
Most Rust grammar rules are defined in terms of printable ASCII-range codepoints,
-but a small number are defined in terms of Unicode properties or explicit codepoint lists.
-^[Substitute definitions for the special Unicode productions are provided to the grammar verifier, restricted to ASCII range, when verifying the grammar in this document.]
+but a small number are defined in terms of Unicode properties or explicit
+codepoint lists. [^inputformat]
+
+[^inputformat]: Substitute definitions for the special Unicode productions are
+ provided to the grammar verifier, restricted to ASCII range, when verifying
+ the grammar in this document.
## Special Unicode Productions
A program that fails to compile due to violation of a compile-time rule has no defined dynamic semantics; the compiler should halt with an error report, and produce no executable artifact.
The compilation model centres on artifacts called _crates_.
-Each compilation processes a single crate in source form, and if successful, produces a single crate in binary form: either an executable or a library.^[A crate is somewhat
-analogous to an *assembly* in the ECMA-335 CLI model, a *library* in the
-SML/NJ Compilation Manager, a *unit* in the Owens and Flatt module system,
-or a *configuration* in Mesa.]
+Each compilation processes a single crate in source form, and if successful,
+produces a single crate in binary form: either an executable or a
+library.[^cratesourcefile]
+
+[^cratesourcefile]: A crate is somewhat analogous to an *assembly* in the
+ ECMA-335 CLI model, a *library* in the SML/NJ Compilation Manager, a *unit*
+ in the Owens and Flatt module system, or a *configuration* in Mesa.
A _crate_ is a unit of compilation and linking, as well as versioning, distribution and runtime loading.
A crate contains a _tree_ of nested [module](#modules) scopes.
# trait Shape { }
# impl Shape for int { }
# let mycircle = 0;
-let myshape: ~Shape = ~mycircle as ~Shape;
+let myshape: Box<Shape> = box mycircle as Box<Shape>;
~~~~
The resulting value is a managed box containing the value that was cast,
fields of a particular variant. For example:
~~~~
-enum List<X> { Nil, Cons(X, ~List<X>) }
+enum List<X> { Nil, Cons(X, Box<List<X>>) }
-let x: List<int> = Cons(10, ~Cons(11, ~Nil));
+let x: List<int> = Cons(10, box Cons(11, box Nil));
match x {
- Cons(_, ~Nil) => fail!("singleton list"),
- Cons(..) => return,
- Nil => fail!("empty list")
+ Cons(_, box Nil) => fail!("singleton list"),
+ Cons(..) => return,
+ Nil => fail!("empty list")
}
~~~~
The first pattern matches lists constructed by applying `Cons` to any head
-value, and a tail value of `~Nil`. The second pattern matches _any_ list
+value, and a tail value of `box Nil`. The second pattern matches _any_ list
constructed with `Cons`, ignoring the values of its arguments. The difference
between `_` and `..` is that the pattern `C(_)` is only type-correct if `C` has
exactly one argument, while the pattern `C(..)` is type-correct for any enum
# fn process_pair(a: int, b: int) { }
# fn process_ten() { }
-enum List<X> { Nil, Cons(X, ~List<X>) }
+enum List<X> { Nil, Cons(X, Box<List<X>>) }
-let x: List<int> = Cons(10, ~Cons(11, ~Nil));
+let x: List<int> = Cons(10, box Cons(11, box Nil));
match x {
- Cons(a, ~Cons(b, _)) => {
+ Cons(a, box Cons(b, _)) => {
process_pair(a,b);
}
Cons(10, _) => {
For example:
~~~~
-enum List { Nil, Cons(uint, ~List) }
+enum List { Nil, Cons(uint, Box<List>) }
fn is_sorted(list: &List) -> bool {
match *list {
- Nil | Cons(_, ~Nil) => true,
- Cons(x, ref r @ ~Cons(y, _)) => (x <= y) && is_sorted(*r)
+ Nil | Cons(_, box Nil) => true,
+ Cons(x, ref r @ box Cons(y, _)) => (x <= y) && is_sorted(*r)
}
}
fn main() {
- let a = Cons(6, ~Cons(7, ~Cons(42, ~Nil)));
+ let a = Cons(6, box Cons(7, box Cons(42, box Nil)));
assert!(is_sorted(&a));
}
The primitive types are the following:
-* The "unit" type `()`, having the single "unit" value `()` (occasionally called "nil").
- ^[The "unit" value `()` is *not* a sentinel "null pointer" value for reference slots; the "unit" type is the implicit return type from functions otherwise lacking a return type, and can be used in other contexts (such as message-sending or type-parametric code) as a zero-size type.]
+* The "unit" type `()`, having the single "unit" value `()` (occasionally called
+ "nil"). [^unittype]
* The boolean type `bool` with values `true` and `false`.
* The machine types.
* The machine-dependent integer and floating-point types.
+[^unittype]: The "unit" value `()` is *not* a sentinel "null pointer" value for
+ reference slots; the "unit" type is the implicit return type from functions
+ otherwise lacking a return type, and can be used in other contexts (such as
+ message-sending or type-parametric code) as a zero-size type.]
+
#### Machine types
The machine types are the following:
* The unsigned word types `u8`, `u16`, `u32` and `u64`, with values drawn from
- the integer intervals $[0, 2^8 - 1]$, $[0, 2^{16} - 1]$, $[0, 2^{32} - 1]$ and
- $[0, 2^{64} - 1]$ respectively.
+ the integer intervals [0, 2^8 - 1], [0, 2^16 - 1], [0, 2^32 - 1] and
+ [0, 2^64 - 1] respectively.
* The signed two's complement word types `i8`, `i16`, `i32` and `i64`, with
- values drawn from the integer intervals $[-(2^7), 2^7 - 1]$,
- $[-(2^{15}), 2^{15} - 1]$, $[-(2^{31}), 2^{31} - 1]$, $[-(2^{63}), 2^{63} - 1]$
+ values drawn from the integer intervals [-(2^(7)), 2^7 - 1],
+ [-(2^(15)), 2^15 - 1], $[-(2^(31)), 2^31 - 1], [-(2^(63)), 2^63 - 1]
respectively.
* The IEEE 754-2008 `binary32` and `binary64` floating-point types: `f32` and
#### Machine-dependent integer types
-The Rust type `uint`^[A Rust `uint` is analogous to a C99 `uintptr_t`.] is an
+The Rust type `uint` [^rustuint] is an
unsigned integer type with target-machine-dependent size. Its size, in
bits, is equal to the number of bits required to hold any memory address on
the target machine.
-The Rust type `int`^[A Rust `int` is analogous to a C99 `intptr_t`.] is a
+The Rust type `int` [^rustint] is a
two's complement signed integer type with target-machine-dependent size. Its
size, in bits, is equal to the size of the rust type `uint` on the same target
machine.
+[^rustuint]: A Rust `uint` is analogous to a C99 `uintptr_t`.
+[^rustint]: A Rust `int` is analogous to a C99 `intptr_t`.
+
### Textual types
The types `char` and `str` hold textual data.
### Structure types
-A `struct` *type* is a heterogeneous product of other types, called the *fields* of the type.
-^[`struct` types are analogous `struct` types in C,
-the *record* types of the ML family,
-or the *structure* types of the Lisp family.]
+A `struct` *type* is a heterogeneous product of other types, called the *fields*
+of the type.[^structtype]
+
+[^structtype]: `struct` types are analogous `struct` types in C,
+ the *record* types of the ML family,
+ or the *structure* types of the Lisp family.
New instances of a `struct` can be constructed with a [struct expression](#structure-expressions).
### Enumerated types
An *enumerated type* is a nominal, heterogeneous disjoint union type,
-denoted by the name of an [`enum` item](#enumerations).
-^[The `enum` type is analogous to a `data` constructor declaration in ML,
-or a *pick ADT* in Limbo.]
+denoted by the name of an [`enum` item](#enumerations). [^enumtype]
+
+[^enumtype]: The `enum` type is analogous to a `data` constructor declaration in
+ ML, or a *pick ADT* in Limbo.
An [`enum` item](#enumerations) declares both the type and a number of *variant constructors*,
each of which is independently named and takes an optional tuple of arguments.
~~~~
enum List<T> {
Nil,
- Cons(T, ~List<T>)
+ Cons(T, Box<List<T>>)
}
-let a: List<int> = Cons(7, ~Cons(13, ~Nil));
+let a: List<int> = Cons(7, box Cons(13, box Nil));
~~~~
### Pointer types
fn to_string(&self) -> ~str { self.to_str() }
}
-fn print(a: ~Printable) {
+fn print(a: Box<Printable>) {
println!("{}", a.to_string());
}
fn main() {
- print(~10 as ~Printable);
+ print(box 10 as Box<Printable>);
}
~~~~
~~~
trait Changer {
fn change(mut self) -> Self;
- fn modify(mut ~self) -> ~Self;
+ fn modify(mut ~self) -> Box<Self>;
}
~~~
### Owned boxes
An _owned box_ is a reference to a heap allocation holding another value, which is constructed
-by the prefix *tilde* sigil `~`.
+by the prefix operator `box`. When the standard library is in use, the type of an owned box is
+`std::owned::Box<T>`.
An example of an owned box type and value:
~~~~
-let x: ~int = ~10;
+
+let x: Box<int> = box 10;
~~~~
Owned box values exist in 1:1 correspondence with their heap allocation
Rust will consider a shallow copy of an owned box to move ownership of the value. After a value has been moved, the source location cannot be used unless it is reinitialized.
~~~~
-let x: ~int = ~10;
+let x: Box<int> = box 10;
let y = x;
// attempting to use `x` will result in an error here
~~~~
the number of concurrent physical CPUs detected at startup.
It's also possible to override this choice at runtime.
When the number of tasks exceeds the number of threads — which is likely —
-the scheduler multiplexes the tasks onto threads.^[
-This is an M:N scheduler,
-which is known to give suboptimal results for CPU-bound concurrency problems.
-In such cases, running with the same number of threads and tasks can yield better results.
-Rust has M:N scheduling in order to support very large numbers of tasks
-in contexts where threads are too resource-intensive to use in large number.
-The cost of threads varies substantially per operating system, and is sometimes quite low,
-so this flexibility is not always worth exploiting.]
+the scheduler multiplexes the tasks onto threads.[^mnscheduler]
+
+[^mnscheduler]: This is an M:N scheduler, which is known to give suboptimal
+ results for CPU-bound concurrency problems. In such cases, running with the
+ same number of threads and tasks can yield better results. Rust has M:N
+ scheduling in order to support very large numbers of tasks in contexts where
+ threads are too resource-intensive to use in large number. The cost of
+ threads varies substantially per operating system, and is sometimes quite
+ low, so this flexibility is not always worth exploiting.
### Communication between tasks
These four log levels correspond to levels 1-4, as controlled by `RUST_LOG`:
-``` {.bash .notrust}
+```notrust,bash
$ RUST_LOG=rust=3 ./rust
This is an error log
This is a warn log
code, the `ignore` string can be added to the three-backtick form of markdown
code block.
- /**
- # nested code fences confuse sundown => indentation + comment to
- # avoid failing tests
- ```
- // This is a testable code block
- ```
+~~~notrust
+```
+// This is a testable code block
+```
- ```ignore
- // This is not a testable code block
- ```
+```ignore
+// This is not a testable code block
+```
- // This is a testable code block (4-space indent)
- */
- # fn foo() {}
+ // This is a testable code block (4-space indent)
+~~~
You can specify that the test's execution should fail with the `should_fail`
directive.
- /**
- # nested code fences confuse sundown => indentation + comment to
- # avoid failing tests
- ```should_fail
- // This code block is expected to generate a failure when run
- ```
- */
- # fn foo() {}
+~~~notrust
+```should_fail
+// This code block is expected to generate a failure when run
+```
+~~~
You can specify that the code block should be compiled but not run with the
`no_run` directive.
- /**
- # nested code fences confuse sundown => indentation + comment to
- # avoid failing tests
- ```no_run
- // This code will be compiled but not executed
- ```
- */
- # fn foo() {}
+~~~notrust
+```no_run
+// This code will be compiled but not executed
+```
+~~~
Rustdoc also supplies some extra sugar for helping with some tedious
documentation examples. If a line is prefixed with `# `, then the line
testing the code block (NB. the space after the `#` is required, so
that one can still write things like `#[deriving(Eq)]`).
- /**
- # nested code fences confuse sundown => indentation + comment to
- # avoid failing tests
- ```rust
- # /!\ The three following lines are comments, which are usually stripped off by
- # the doc-generating tool. In order to display them anyway in this particular
- # case, the character following the leading '#' is not a usual space like in
- # these first five lines but a non breakable one.
- #
- #Â // showing 'fib' in this documentation would just be tedious and detracts from
- #Â // what's actually being documented.
- #Â fn fib(n: int) { n + 2 }
-
- spawn(proc() { fib(200); })
- ```
- */
- # fn foo() {}
+~~~notrust
+```
+# /!\ The three following lines are comments, which are usually stripped off by
+# the doc-generating tool. In order to display them anyway in this particular
+# case, the character following the leading '#' is not a usual space like in
+# these first five lines but a non breakable one.
+#Â // showing 'fib' in this documentation would just be tedious and detracts from
+#Â // what's actually being documented.
+#Â fn fib(n: int) { n + 2 }
+
+spawn(proc() { fib(200); })
+```
+~~~
The documentation online would look like `spawn(proc() { fib(200); })`, but when
testing this code, the `fib` function will be included (so it can compile).
with the `--test-args` flag.
~~~ {.notrust}
-$ # Only run tests containing 'foo' in their name
+# Only run tests containing 'foo' in their name
$ rustdoc --test lib.rs --test-args 'foo'
-$ # See what's possible when running tests
+# See what's possible when running tests
$ rustdoc --test lib.rs --test-args '--help'
~~~
dynamic failures are possible from accessing freed resources. When a task
fails, destructors of all objects in the task are called.
-The `~` sigil represents a unique handle for a memory allocation on the heap:
+The `box` operator performs memory allocation on the heap:
~~~~
{
// an integer allocated on the heap
- let y = ~10;
+ let y = box 10;
}
// the destructor frees the heap memory as soon as `y` goes out of scope
~~~~
~~~~
// the struct owns the objects contained in the `x` and `y` fields
-struct Foo { x: int, y: ~int }
+struct Foo { x: int, y: Box<int> }
{
// `a` is the owner of the struct, and thus the owner of the struct's fields
- let a = Foo { x: 5, y: ~10 };
+ let a = Foo { x: 5, y: box 10 };
}
// when `a` goes out of scope, the destructor for the `~int` in the struct's
// field is called
// `b` is mutable, and the mutability is inherited by the objects it owns
-let mut b = Foo { x: 5, y: ~10 };
+let mut b = Foo { x: 5, y: box 10 };
b.x = 10;
~~~~
directly inside `Cons`, making it at least as big as the sum of both types. The
type was invalid because the size was infinite!
-An *owned box* (`~`) uses a dynamic memory allocation to provide the invariant
-of always being the size of a pointer, regardless of the contained type. This
-can be leveraged to create a valid `List` definition:
+An *owned box* (`Box`, located in the `std::owned` module) uses a dynamic memory
+allocation to provide the invariant of always being the size of a pointer,
+regardless of the contained type. This can be leveraged to create a valid `List`
+definition:
~~~
+
enum List {
- Cons(u32, ~List),
+ Cons(u32, Box<List>),
Nil
}
~~~
~~~
# enum List {
-# Cons(u32, ~List),
+# Cons(u32, Box<List>),
# Nil
# }
-let list = Cons(1, ~Cons(2, ~Cons(3, ~Nil)));
+let list = Cons(1, box Cons(2, box Cons(3, box Nil)));
~~~
It represents an owned tree of values, inheriting mutability down the tree and
~~~ {.notrust}
List box List box List box List box
+--------------+ +--------------+ +--------------+ +----------+
-list -> | Cons | 1 | ~ | -> | Cons | 2 | ~ | -> | Cons | 3 | ~ | -> | Nil |
+list -> | Cons | 1 | | -> | Cons | 2 | | -> | Cons | 3 | | -> | Nil |
+--------------+ +--------------+ +--------------+ +----------+
~~~
~~~
# enum List {
-# Cons(u32, ~List),
+# Cons(u32, Box<List>),
# Nil
# }
-let xs = Cons(1, ~Cons(2, ~Cons(3, ~Nil)));
+let xs = Cons(1, box Cons(2, box Cons(3, box Nil)));
let ys = xs; // copies `Cons(u32, pointer)` shallowly
~~~
~~~
# enum List {
-# Cons(u32, ~List),
+# Cons(u32, Box<List>),
# Nil
# }
let mut xs = Nil;
Avoiding a move can be done with the library-defined `clone` method:
~~~~
-let x = ~5;
+let x = box 5;
let y = x.clone(); // `y` is a newly allocated box
let z = x; // no new memory allocated, `x` can no longer be used
~~~~
~~~{.ignore}
#[deriving(Clone)]
enum List {
- Cons(u32, ~List),
+ Cons(u32, Box<List>),
Nil
}
-let x = Cons(5, ~Nil);
+let x = Cons(5, box Nil);
let y = x.clone();
// `x` can still be used!
The mutability of a value may be changed by moving it to a new owner:
~~~~
-let r = ~13;
+let r = box 13;
let mut s = r; // box becomes mutable
*s += 1;
let t = s; // box becomes immutable
~~~
enum List {
- Cons(u32, ~List),
+ Cons(u32, Box<List>),
Nil
}
fn prepend(xs: List, value: u32) -> List {
- Cons(value, ~xs)
+ Cons(value, box xs)
}
let mut xs = Nil;
~~~
# enum List {
-# Cons(u32, ~List),
+# Cons(u32, Box<List>),
# Nil
# }
fn eq(xs: &List, ys: &List) -> bool {
// If we have reached the end of both lists, they are equal.
(&Nil, &Nil) => true,
// If the current elements of both lists are equal, keep going.
- (&Cons(x, ~ref next_xs), &Cons(y, ~ref next_ys))
+ (&Cons(x, box ref next_xs), &Cons(y, box ref next_ys))
if x == y => eq(next_xs, next_ys),
// If the current elements are not equal, the lists are not equal.
_ => false
}
}
-let xs = Cons(5, ~Cons(10, ~Nil));
-let ys = Cons(5, ~Cons(10, ~Nil));
+let xs = Cons(5, box Cons(10, box Nil));
+let ys = Cons(5, box Cons(10, box Nil));
assert!(eq(&xs, &ys));
~~~
~~~
enum List<T> {
- Cons(T, ~List<T>),
+ Cons(T, Box<List<T>>),
Nil
}
~~~
~~~
# enum List<T> {
-# Cons(T, ~List<T>),
+# Cons(T, Box<List<T>>),
# Nil
# }
fn prepend<T>(xs: List<T>, value: T) -> List<T> {
- Cons(value, ~xs)
+ Cons(value, box xs)
}
~~~
~~~
# enum List<T> {
-# Cons(T, ~List<T>),
+# Cons(T, Box<List<T>>),
# Nil
# }
# fn prepend<T>(xs: List<T>, value: T) -> List<T> {
-# Cons(value, ~xs)
+# Cons(value, box xs)
# }
let mut xs = Nil; // Unknown type! This is a `List<T>`, but `T` can be anything.
xs = prepend(xs, 10); // Here the compiler infers `xs`'s type as `List<int>`.
~~~
# enum List<T> {
-# Cons(T, ~List<T>),
+# Cons(T, Box<List<T>>),
# Nil
# }
# fn prepend<T>(xs: List<T>, value: T) -> List<T> {
-# Cons(value, ~xs)
+# Cons(value, box xs)
# }
let mut xs: List<int> = Nil::<int>;
xs = prepend::<int>(xs, 10);
~~~
# enum List<T> {
-# Cons(T, ~List<T>),
+# Cons(T, Box<List<T>>),
# Nil
# }
fn eq<T: Eq>(xs: &List<T>, ys: &List<T>) -> bool {
// If we have reached the end of both lists, they are equal.
(&Nil, &Nil) => true,
// If the current elements of both lists are equal, keep going.
- (&Cons(ref x, ~ref next_xs), &Cons(ref y, ~ref next_ys))
+ (&Cons(ref x, box ref next_xs), &Cons(ref y, box ref next_ys))
if x == y => eq(next_xs, next_ys),
// If the current elements are not equal, the lists are not equal.
_ => false
}
}
-let xs = Cons('c', ~Cons('a', ~Cons('t', ~Nil)));
-let ys = Cons('c', ~Cons('a', ~Cons('t', ~Nil)));
+let xs = Cons('c', box Cons('a', box Cons('t', box Nil)));
+let ys = Cons('c', box Cons('a', box Cons('t', box Nil)));
assert!(eq(&xs, &ys));
~~~
~~~
# enum List<T> {
-# Cons(T, ~List<T>),
+# Cons(T, Box<List<T>>),
# Nil
# }
impl<T: Eq> Eq for List<T> {
// If we have reached the end of both lists, they are equal.
(&Nil, &Nil) => true,
// If the current elements of both lists are equal, keep going.
- (&Cons(ref x, ~ref next_xs), &Cons(ref y, ~ref next_ys))
+ (&Cons(ref x, box ref next_xs), &Cons(ref y, box ref next_ys))
if x == y => next_xs == next_ys,
// If the current elements are not equal, the lists are not equal.
_ => false
}
}
-let xs = Cons(5, ~Cons(10, ~Nil));
-let ys = Cons(5, ~Cons(10, ~Nil));
+let xs = Cons(5, box Cons(10, box Nil));
+let ys = Cons(5, box Cons(10, box Nil));
// The methods below are part of the Eq trait,
// which we implemented on our linked list.
assert!(xs.eq(&ys));
(5, 5, 5, 5, 5, 5)
}
-let x = ~foo(); // allocates a `~` box, and writes the integers directly to it
+let x = box foo(); // allocates a box, and writes the integers directly to it
~~~~
Beyond the properties granted by the size, an owned box behaves as a regular
let mut y = 5; // mutable
y += 2;
-let x = ~5; // immutable
-let mut y = ~5; // mutable
+let x = box 5; // immutable
+let mut y = box 5; // mutable
*y += 2; // the `*` operator is needed to access the contained value
~~~~
x: f64,
y: f64
}
-~~~~
+~~~
We can use this simple definition to allocate points in many different
ways. For example, in this code, each of these local variables
~~~
# struct Point { x: f64, y: f64 }
-let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
-let owned_box : ~Point = ~Point { x: 7.0, y: 9.0 };
+let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
+let owned_box : Box<Point> = box Point { x: 7.0, y: 9.0 };
~~~
Suppose we want to write a procedure that computes the distance
~~~
# struct Point{ x: f64, y: f64 };
-# let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
-# let owned_box : ~Point = ~Point { x: 7.0, y: 9.0 };
+# let on_the_stack : Point = Point { x: 3.0, y: 4.0 };
+# let owned_box : Box<Point> = box Point { x: 7.0, y: 9.0 };
# fn compute_distance(p1: &Point, p2: &Point) -> f64 { 0.0 }
compute_distance(&on_the_stack, owned_box);
~~~
In the case of `owned_box`, however, no
explicit action is necessary. The compiler will automatically convert
-a box `~point` to a reference like
+a box `box point` to a reference like
`&point`. This is another form of borrowing; in this case, the
contents of the owned box are being lent out.
box or pointer, similarly to C.
~~~
-let owned = ~10;
+let owned = box 10;
let borrowed = &20;
let sum = *owned + *borrowed;
points to.
~~~
-let mut owned = ~10;
+let mut owned = box 10;
let mut value = 20;
let borrowed = &mut value;
# struct Point { x: f64, y: f64 }
# enum Shape { Rectangle(Point, Point) }
# impl Shape { fn area(&self) -> int { 0 } }
-let start = ~Point { x: 10.0, y: 20.0 };
-let end = ~Point { x: (*start).x + 100.0, y: (*start).y + 100.0 };
+let start = box Point { x: 10.0, y: 20.0 };
+let end = box Point { x: (*start).x + 100.0, y: (*start).y + 100.0 };
let rect = &Rectangle(*start, *end);
let area = (*rect).area();
~~~
# struct Point { x: f64, y: f64 }
# enum Shape { Rectangle(Point, Point) }
# impl Shape { fn area(&self) -> int { 0 } }
-let start = ~Point { x: 10.0, y: 20.0 };
-let end = ~Point { x: start.x + 100.0, y: start.y + 100.0 };
+let start = box Point { x: 10.0, y: 20.0 };
+let end = box Point { x: start.x + 100.0, y: start.y + 100.0 };
let rect = &Rectangle(*start, *end);
let area = rect.area();
~~~
~~~
# struct Point { x: f64, y: f64 }
-let point = &~Point { x: 10.0, y: 20.0 };
+let point = &box Point { x: 10.0, y: 20.0 };
println!("{:f}", point.x);
~~~
let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0);
(&s).draw_reference();
-(~s).draw_owned();
+(box s).draw_owned();
s.draw_value();
~~~
// As with typical function arguments, owned pointers
// are automatically converted to references
-(~s).draw_reference();
+(box s).draw_reference();
// Unlike typical function arguments, the self value will
// automatically be referenced ...
(& &s).draw_reference();
// ... and dereferenced and borrowed
-(&~s).draw_reference();
+(&box s).draw_reference();
~~~
Implementations may also define standalone (sometimes called "static")
~~~~
# trait Drawable { fn draw(&self); }
-fn draw_all(shapes: &[~Drawable]) {
+fn draw_all(shapes: &[Box<Drawable>]) {
for shape in shapes.iter() { shape.draw(); }
}
~~~~
# trait Drawable { fn draw(&self); }
# fn new_circle() -> Circle { 1 }
# fn new_rectangle() -> Rectangle { true }
-# fn draw_all(shapes: &[~Drawable]) {}
+# fn draw_all(shapes: &[Box<Drawable>]) {}
impl Drawable for Circle { fn draw(&self) { /* ... */ } }
impl Drawable for Rectangle { fn draw(&self) { /* ... */ } }
-let c: ~Circle = ~new_circle();
-let r: ~Rectangle = ~new_rectangle();
-draw_all([c as ~Drawable, r as ~Drawable]);
+let c: Box<Circle> = box new_circle();
+let r: Box<Rectangle> = box new_rectangle();
+draw_all([c as Box<Drawable>, r as Box<Drawable>]);
~~~~
We omit the code for `new_circle` and `new_rectangle`; imagine that
only be referred to via one of the pointer types.
Other pointer types work as well.
Casts to traits may only be done with compatible pointers so,
-for example, an `&Circle` may not be cast to an `~Drawable`.
+for example, an `&Circle` may not be cast to a `Box<Drawable>`.
~~~
# type Circle = int; type Rectangle = int;
# fn new_circle() -> int { 1 }
# fn new_rectangle() -> int { 2 }
// An owned object
-let owny: ~Drawable = ~new_circle() as ~Drawable;
+let owny: Box<Drawable> = box new_circle() as Box<Drawable>;
// A borrowed object
let stacky: &Drawable = &new_circle() as &Drawable;
~~~
trait Foo {}
trait Bar<T> {}
-fn sendable_foo(f: ~Foo:Send) { /* ... */ }
+fn sendable_foo(f: Box<Foo:Send>) { /* ... */ }
fn shareable_bar<T: Share>(b: &Bar<T>: Share) { /* ... */ }
~~~
~~~{.ignore}
// `a.rs` - crate root
use b::foo;
+use b::c::bar;
mod b;
-fn main() { foo(); }
+fn main() {
+ foo();
+ bar();
+}
~~~
~~~{.ignore}
-// `b.rs`
-use b::c::bar;
+// `b/mod.rs`
pub mod c;
-pub fn foo() { bar(); }
+pub fn foo() { println!("Foo!"; }
~~~
-~~~
-// `c.rs`
-pub fn bar() { println!("Baz!"); }
-# fn main() {}
+~~~{.ignore}
+// `b/c.rs`
+pub fn bar() { println!("Bar!"); }
~~~
There also exist two short forms for importing multiple names at once:
use std::cast::{transmute, transmute_mut_lifetime};
use std::cast;
use std::cell::{Cell, RefCell};
-use std::mem;
-use std::ptr::read;
use std::cmp;
+use std::intrinsics::{TyDesc, get_tydesc};
+use std::intrinsics;
+use std::mem;
use std::num;
+use std::ptr::read;
use std::rc::Rc;
use std::rt::global_heap;
-use std::intrinsics::{TyDesc, get_tydesc};
-use std::intrinsics;
// The way arena uses arrays is really deeply awful. The arrays are
// allocated, and have capacities reserved, but the fill for the array
end: *T,
/// A pointer to the first arena segment.
- first: Option<~TypedArenaChunk<T>>,
+ first: Option<Box<TypedArenaChunk<T>>>,
}
struct TypedArenaChunk<T> {
/// Pointer to the next arena segment.
- next: Option<~TypedArenaChunk<T>>,
+ next: Option<Box<TypedArenaChunk<T>>>,
/// The number of elements that this chunk can hold.
capacity: uint,
impl<T> TypedArenaChunk<T> {
#[inline]
- fn new(next: Option<~TypedArenaChunk<T>>, capacity: uint) -> ~TypedArenaChunk<T> {
+ fn new(next: Option<Box<TypedArenaChunk<T>>>, capacity: uint)
+ -> Box<TypedArenaChunk<T>> {
let mut size = mem::size_of::<TypedArenaChunk<T>>();
size = round_up(size, mem::min_align_of::<T>());
let elem_size = mem::size_of::<T>();
let mut chunk = unsafe {
let chunk = global_heap::exchange_malloc(size);
- let mut chunk: ~TypedArenaChunk<T> = cast::transmute(chunk);
+ let mut chunk: Box<TypedArenaChunk<T>> = cast::transmute(chunk);
mem::move_val_init(&mut chunk.next, next);
chunk
};
enum Op {Union, Intersect, Assign, Difference}
/// The bitvector type
+///
+/// # Example
+///
+/// ```rust
+/// use collections::bitv::Bitv;
+///
+/// let mut bv = Bitv::new(10, false);
+///
+/// // insert all primes less than 10
+/// bv.set(2, true);
+/// bv.set(3, true);
+/// bv.set(5, true);
+/// bv.set(7, true);
+/// println!("{}", bv.to_str());
+/// println!("total bits set to true: {}", bv.iter().count(|x| x));
+///
+/// // flip all values in bitvector, producing non-primes less than 10
+/// bv.negate();
+/// println!("{}", bv.to_str());
+/// println!("total bits set to true: {}", bv.iter().count(|x| x));
+///
+/// // reset bitvector to empty
+/// bv.clear();
+/// println!("{}", bv.to_str());
+/// println!("total bits set to true: {}", bv.iter().count(|x| x));
+/// ```
#[deriving(Clone)]
pub struct Bitv {
/// Internal representation of the bit vector (small or large)
}
}
}
-
}
impl Bitv {
+ /// Creates an empty Bitv that holds `nbits` elements, setting each element
+ /// to `init`.
pub fn new(nbits: uint, init: bool) -> Bitv {
let rep = if nbits < uint::BITS {
Small(SmallBitv::new(if init {(1<<nbits)-1} else {0}))
}
}
+ /// Returns an iterator over the elements of the vector in order.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// use collections::bitv::Bitv;
+ /// let mut bv = Bitv::new(10, false);
+ /// bv.set(1, true);
+ /// bv.set(2, true);
+ /// bv.set(3, true);
+ /// bv.set(5, true);
+ /// bv.set(8, true);
+ /// // Count bits set to 1; result should be 5
+ /// println!("{}", bv.iter().count(|x| x));
+ /// ```
#[inline]
pub fn iter<'a>(&'a self) -> Bits<'a> {
Bits {bitv: self, next_idx: 0, end_idx: self.nbits}
}
///Creates a new branch node given a vector of an elements and a pointer to a rightmost child.
- fn new_branch(vec: Vec<BranchElt<K, V>>, right: ~Node<K, V>) -> Node<K, V> {
+ fn new_branch(vec: Vec<BranchElt<K, V>>, right: Box<Node<K, V>>)
+ -> Node<K, V> {
BranchNode(Branch::new(vec, right))
}
//Vector of values with children, plus a rightmost child (greater than all)
struct Branch<K, V> {
elts: Vec<BranchElt<K,V>>,
- rightmost_child: ~Node<K, V>
+ rightmost_child: Box<Node<K, V>>,
}
impl<K: TotalOrd, V> Branch<K, V> {
///Creates a new Branch from a vector of BranchElts and a rightmost child (a node).
- fn new(vec: Vec<BranchElt<K, V>>, right: ~Node<K, V>) -> Branch<K, V> {
+ fn new(vec: Vec<BranchElt<K, V>>, right: Box<Node<K, V>>)
+ -> Branch<K, V> {
Branch {
elts: vec,
rightmost_child: right
//A BranchElt has a left child in insertion to a key-value pair.
struct BranchElt<K, V> {
- left: ~Node<K, V>,
+ left: Box<Node<K, V>>,
key: K,
value: V
}
impl<K: TotalOrd, V> BranchElt<K, V> {
///Creates a new BranchElt from a supplied key, value, and left child.
- fn new(k: K, v: V, n: ~Node<K, V>) -> BranchElt<K, V> {
+ fn new(k: K, v: V, n: Box<Node<K, V>>) -> BranchElt<K, V> {
BranchElt {
left: n,
key: k,
//! DList implements the trait Deque. It should be imported with `use
//! collections::deque::Deque`.
-
// DList is constructed like a singly-linked list over the field `next`.
// including the last link being None; each Node owns its `next` field.
//
// the reverse direction.
use std::cast;
-use std::mem::{replace, swap};
-use std::ptr;
use std::iter::Rev;
use std::iter;
+use std::mem::{replace, swap};
+use std::ptr;
use deque::Deque;
list_tail: Rawlink<Node<T>>,
}
-type Link<T> = Option<~Node<T>>;
+type Link<T> = Option<Box<Node<T>>>;
struct Rawlink<T> { p: *mut T }
struct Node<T> {
}
/// Set the .prev field on `next`, then return `Some(next)`
-fn link_with_prev<T>(mut next: ~Node<T>, prev: Rawlink<Node<T>>) -> Link<T> {
+fn link_with_prev<T>(mut next: Box<Node<T>>, prev: Rawlink<Node<T>>)
+ -> Link<T> {
next.prev = prev;
Some(next)
}
impl<T> DList<T> {
/// Add a Node first in the list
#[inline]
- fn push_front_node(&mut self, mut new_head: ~Node<T>) {
+ fn push_front_node(&mut self, mut new_head: Box<Node<T>>) {
match self.list_head {
None => {
self.list_tail = Rawlink::some(new_head);
/// Remove the first Node and return it, or None if the list is empty
#[inline]
- fn pop_front_node(&mut self) -> Option<~Node<T>> {
+ fn pop_front_node(&mut self) -> Option<Box<Node<T>>> {
self.list_head.take().map(|mut front_node| {
self.length -= 1;
match front_node.next.take() {
/// Add a Node last in the list
#[inline]
- fn push_back_node(&mut self, mut new_tail: ~Node<T>) {
+ fn push_back_node(&mut self, mut new_tail: Box<Node<T>>) {
match self.list_tail.resolve() {
None => return self.push_front_node(new_tail),
Some(tail) => {
/// Remove the last Node and return it, or None if the list is empty
#[inline]
- fn pop_back_node(&mut self) -> Option<~Node<T>> {
+ fn pop_back_node(&mut self) -> Option<Box<Node<T>>> {
self.list_tail.resolve().map_or(None, |tail| {
self.length -= 1;
self.list_tail = tail.prev;
///
/// O(1)
fn pop_front(&mut self) -> Option<T> {
- self.pop_front_node().map(|~Node{value, ..}| value)
+ self.pop_front_node().map(|box Node{value, ..}| value)
}
/// Add an element last in the list
///
/// O(1)
fn pop_back(&mut self) -> Option<T> {
- self.pop_back_node().map(|~Node{value, ..}| value)
+ self.pop_back_node().map(|box Node{value, ..}| value)
}
}
match tail.resolve() {
None => break,
Some(prev) => {
- prev.next.take(); // release ~Node<T>
+ prev.next.take(); // release Box<Node<T>>
tail = prev.prev;
}
}
// private methods for MutItems
impl<'a, A> MutItems<'a, A> {
- fn insert_next_node(&mut self, mut ins_node: ~Node<A>) {
+ fn insert_next_node(&mut self, mut ins_node: Box<Node<A>>) {
// Insert before `self.head` so that it is between the
// previously yielded element and self.head.
//
#[test]
fn test_basic() {
- let mut m: DList<~int> = DList::new();
+ let mut m: DList<Box<int>> = DList::new();
assert_eq!(m.pop_front(), None);
assert_eq!(m.pop_back(), None);
assert_eq!(m.pop_front(), None);
m.push_front(box 1);
- assert_eq!(m.pop_front(), Some(~1));
+ assert_eq!(m.pop_front(), Some(box 1));
m.push_back(box 2);
m.push_back(box 3);
assert_eq!(m.len(), 2);
- assert_eq!(m.pop_front(), Some(~2));
- assert_eq!(m.pop_front(), Some(~3));
+ assert_eq!(m.pop_front(), Some(box 2));
+ assert_eq!(m.pop_front(), Some(box 3));
assert_eq!(m.len(), 0);
assert_eq!(m.pop_front(), None);
m.push_back(box 1);
m.push_back(box 3);
m.push_back(box 5);
m.push_back(box 7);
- assert_eq!(m.pop_front(), Some(~1));
+ assert_eq!(m.pop_front(), Some(box 1));
let mut n = DList::new();
n.push_front(2);
/// An LRU Cache.
pub struct LruCache<K, V> {
- map: HashMap<KeyRef<K>, ~LruEntry<K, V>>,
+ map: HashMap<KeyRef<K>, Box<LruEntry<K, V>>>,
max_size: uint,
head: *mut LruEntry<K, V>,
}
impl<K, V> Drop for LruCache<K, V> {
fn drop(&mut self) {
unsafe {
- let node: ~LruEntry<K, V> = cast::transmute(self.head);
+ let node: Box<LruEntry<K, V>> = cast::transmute(self.head);
// Prevent compiler from trying to drop the un-initialized field in the sigil node.
- let ~LruEntry { key: k, value: v, .. } = node;
+ let box LruEntry { key: k, value: v, .. } = node;
cast::forget(k);
cast::forget(v);
}
#[test]
fn test_push_unique() {
- let mut heap = PriorityQueue::from_vec(vec!(~2, ~4, ~9));
+ let mut heap = PriorityQueue::from_vec(vec!(box 2, box 4, box 9));
assert_eq!(heap.len(), 3);
- assert!(*heap.top() == ~9);
+ assert!(*heap.top() == box 9);
heap.push(box 11);
assert_eq!(heap.len(), 4);
- assert!(*heap.top() == ~11);
+ assert!(*heap.top() == box 11);
heap.push(box 5);
assert_eq!(heap.len(), 5);
- assert!(*heap.top() == ~11);
+ assert!(*heap.top() == box 11);
heap.push(box 27);
assert_eq!(heap.len(), 6);
- assert!(*heap.top() == ~27);
+ assert!(*heap.top() == box 27);
heap.push(box 3);
assert_eq!(heap.len(), 7);
- assert!(*heap.top() == ~27);
+ assert!(*heap.top() == box 27);
heap.push(box 103);
assert_eq!(heap.len(), 8);
- assert!(*heap.top() == ~103);
+ assert!(*heap.top() == box 103);
}
#[test]
assert!(!called);
called = true;
assert_eq!(k, 1);
- assert_eq!(v, ~2);
+ assert_eq!(v, box 2);
}
assert!(called);
m.insert(2, box 1);
#[allow(missing_doc)]
#[deriving(Clone)]
pub struct TreeMap<K, V> {
- root: Option<~TreeNode<K, V>>,
+ root: Option<Box<TreeNode<K, V>>>,
length: uint
}
impl<K: TotalOrd, V> Map<K, V> for TreeMap<K, V> {
fn find<'a>(&'a self, key: &K) -> Option<&'a V> {
- let mut current: &'a Option<~TreeNode<K, V>> = &self.root;
+ let mut current: &'a Option<Box<TreeNode<K, V>>> = &self.root;
loop {
match *current {
Some(ref r) => {
let TreeMap { root: root, length: length } = self;
let stk = match root {
None => vec!(),
- Some(~tn) => vec!(tn)
+ Some(box tn) => vec!(tn)
};
MoveEntries {
stack: stk,
($name:ident,
$rev_name:ident,
- // the function to go from &m Option<~TreeNode> to *m TreeNode
+ // the function to go from &m Option<Box<TreeNode>> to *m TreeNode
deref = $deref:ident,
// see comment on `addr!`, this is just an optional `mut`, but
addr_mut = mut
}
-fn deref<'a, K, V>(node: &'a Option<~TreeNode<K, V>>) -> *TreeNode<K, V> {
+fn deref<'a, K, V>(node: &'a Option<Box<TreeNode<K, V>>>) -> *TreeNode<K, V> {
match *node {
Some(ref n) => {
let n: &TreeNode<K, V> = *n;
}
}
-fn mut_deref<K, V>(x: &mut Option<~TreeNode<K, V>>) -> *mut TreeNode<K, V> {
+fn mut_deref<K, V>(x: &mut Option<Box<TreeNode<K, V>>>)
+ -> *mut TreeNode<K, V> {
match *x {
Some(ref mut n) => {
let n: &mut TreeNode<K, V> = *n;
} = self.stack.pop().unwrap();
match left {
- Some(~left) => {
+ Some(box left) => {
let n = TreeNode {
key: key,
value: value,
}
None => {
match right {
- Some(~right) => self.stack.push(right),
+ Some(box right) => self.stack.push(right),
None => ()
}
self.remaining -= 1;
struct TreeNode<K, V> {
key: K,
value: V,
- left: Option<~TreeNode<K, V>>,
- right: Option<~TreeNode<K, V>>,
+ left: Option<Box<TreeNode<K, V>>>,
+ right: Option<Box<TreeNode<K, V>>>,
level: uint
}
}
// Remove left horizontal link by rotating right
-fn skew<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>) {
+fn skew<K: TotalOrd, V>(node: &mut Box<TreeNode<K, V>>) {
if node.left.as_ref().map_or(false, |x| x.level == node.level) {
let mut save = node.left.take_unwrap();
swap(&mut node.left, &mut save.right); // save.right now None
// Remove dual horizontal link by rotating left and increasing level of
// the parent
-fn split<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>) {
+fn split<K: TotalOrd, V>(node: &mut Box<TreeNode<K, V>>) {
if node.right.as_ref().map_or(false,
|x| x.right.as_ref().map_or(false, |y| y.level == node.level)) {
let mut save = node.right.take_unwrap();
}
}
-fn find_mut<'r, K: TotalOrd, V>(node: &'r mut Option<~TreeNode<K, V>>,
+fn find_mut<'r, K: TotalOrd, V>(node: &'r mut Option<Box<TreeNode<K, V>>>,
key: &K)
-> Option<&'r mut V> {
match *node {
}
}
-fn insert<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
+fn insert<K: TotalOrd, V>(node: &mut Option<Box<TreeNode<K, V>>>,
key: K, value: V) -> Option<V> {
match *node {
Some(ref mut save) => {
}
}
-fn remove<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
+fn remove<K: TotalOrd, V>(node: &mut Option<Box<TreeNode<K, V>>>,
key: &K) -> Option<V> {
- fn heir_swap<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>,
- child: &mut Option<~TreeNode<K, V>>) {
+ fn heir_swap<K: TotalOrd, V>(node: &mut Box<TreeNode<K, V>>,
+ child: &mut Option<Box<TreeNode<K, V>>>) {
// *could* be done without recursion, but it won't borrow check
for x in child.mut_iter() {
if x.right.is_some() {
(remove(&mut save.left, key), true)
} else {
let new = save.left.take_unwrap();
- let ~TreeNode{value, ..} = replace(save, new);
+ let box TreeNode{value, ..} = replace(save, new);
*save = save.left.take_unwrap();
(Some(value), true)
}
} else if save.right.is_some() {
let new = save.right.take_unwrap();
- let ~TreeNode{value, ..} = replace(save, new);
+ let box TreeNode{value, ..} = replace(save, new);
(Some(value), true)
} else {
(None, false)
}
}
return match node.take() {
- Some(~TreeNode{value, ..}) => Some(value), None => fail!()
+ Some(box TreeNode{value, ..}) => Some(value), None => fail!()
};
}
#[cfg(test)]
mod test_treemap {
-
use super::{TreeMap, TreeNode};
use rand::Rng;
}
}
- fn check_left<K: TotalOrd, V>(node: &Option<~TreeNode<K, V>>,
- parent: &~TreeNode<K, V>) {
+ fn check_left<K: TotalOrd, V>(node: &Option<Box<TreeNode<K, V>>>,
+ parent: &Box<TreeNode<K, V>>) {
match *node {
Some(ref r) => {
assert_eq!(r.key.cmp(&parent.key), Less);
}
}
- fn check_right<K: TotalOrd, V>(node: &Option<~TreeNode<K, V>>,
- parent: &~TreeNode<K, V>,
+ fn check_right<K: TotalOrd, V>(node: &Option<Box<TreeNode<K, V>>>,
+ parent: &Box<TreeNode<K, V>>,
parent_red: bool) {
match *node {
Some(ref r) => {
//! Ordered containers with integer keys, implemented as radix tries (`TrieSet` and `TrieMap` types)
-use std::mem;
-use std::uint;
use std::mem::init;
-use std::slice;
+use std::mem;
use std::slice::{Items, MutItems};
+use std::slice;
+use std::uint;
// FIXME: #5244: need to manually update the TrieNode constructor
static SHIFT: uint = 4;
static NUM_CHUNKS: uint = uint::BITS / SHIFT;
enum Child<T> {
- Internal(~TrieNode<T>),
+ Internal(Box<TrieNode<T>>),
External(uint, T),
Nothing
}
let little_val = fourcc!("foo ", little);
assert_eq!(little_val, 0x21EEFFC0u32);
}
- ```
+```
# References
#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
register(token::intern("fourcc"),
- NormalTT(~BasicMacroExpander {
+ NormalTT(box BasicMacroExpander {
expander: expand_syntax_ext,
span: None,
},
None));
}
-pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
+pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+ -> Box<base::MacResult> {
let (expr, endian) = parse_tts(cx, tts);
let little = match endian {
// Note 2: Once Dynamically Sized Types (DST) lands, it might be
// reasonable to replace this with something like `enum MaybeOwned<'a,
-// Sized? U>{ Owned(~U), Borrowed(&'a U) }`; and then `U` could be
+// Sized? U>{ Owned(Box<U>), Borrowed(&'a U) }`; and then `U` could be
// instantiated with `[T]` or `str`, etc. Of course, that would imply
// removing the `Growable` variant, which relates to note 1 above.
// Alternatively, we might add `MaybeOwned` for the general case but
use std::cast;
use std::mem::replace;
-use std::rt::rtio::{EventLoop, IoFactory, RemoteCallback, PausableIdleCallback,
- Callback};
+use std::rt::rtio::{EventLoop, IoFactory, RemoteCallback};
+use std::rt::rtio::{PausableIdleCallback, Callback};
use std::unstable::sync::Exclusive;
/// This is the only exported function from this module.
-pub fn event_loop() -> ~EventLoop:Send {
- box BasicLoop::new() as ~EventLoop:Send
+pub fn event_loop() -> Box<EventLoop:Send> {
+ box BasicLoop::new() as Box<EventLoop:Send>
}
struct BasicLoop {
work: Vec<proc():Send>, // pending work
idle: Option<*mut BasicPausable>, // only one is allowed
- remotes: Vec<(uint, ~Callback:Send)>,
+ remotes: Vec<(uint, Box<Callback:Send>)>,
next_remote: uint,
messages: Exclusive<Vec<Message>>,
}
}
// FIXME: Seems like a really weird requirement to have an event loop provide.
- fn pausable_idle_callback(&mut self, cb: ~Callback:Send)
- -> ~PausableIdleCallback:Send
- {
+ fn pausable_idle_callback(&mut self, cb: Box<Callback:Send>)
+ -> Box<PausableIdleCallback:Send> {
let callback = box BasicPausable::new(self, cb);
rtassert!(self.idle.is_none());
unsafe {
let cb_ptr: &*mut BasicPausable = cast::transmute(&callback);
self.idle = Some(*cb_ptr);
}
- callback as ~PausableIdleCallback:Send
+ callback as Box<PausableIdleCallback:Send>
}
- fn remote_callback(&mut self, f: ~Callback:Send) -> ~RemoteCallback:Send {
+ fn remote_callback(&mut self, f: Box<Callback:Send>)
+ -> Box<RemoteCallback:Send> {
let id = self.next_remote;
self.next_remote += 1;
self.remotes.push((id, f));
- box BasicRemote::new(self.messages.clone(), id) as ~RemoteCallback:Send
+ box BasicRemote::new(self.messages.clone(), id) as
+ Box<RemoteCallback:Send>
}
fn io<'a>(&'a mut self) -> Option<&'a mut IoFactory> { None }
struct BasicPausable {
eloop: *mut BasicLoop,
- work: ~Callback:Send,
+ work: Box<Callback:Send>,
active: bool,
}
impl BasicPausable {
- fn new(eloop: &mut BasicLoop, cb: ~Callback:Send) -> BasicPausable {
+ fn new(eloop: &mut BasicLoop, cb: Box<Callback:Send>) -> BasicPausable {
BasicPausable {
active: false,
work: cb,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use stack::Stack;
use std::uint;
use std::cast::{transmute, transmute_mut_unsafe};
-use stack::Stack;
use std::rt::stack;
use std::raw;
// FIXME #7761: Registers is boxed so that it is 16-byte aligned, for storing
// SSE regs. It would be marginally better not to do this. In C++ we
// use an attribute on a struct.
-// FIXME #7761: It would be nice to define regs as `~Option<Registers>` since
-// the registers are sometimes empty, but the discriminant would
+// FIXME #7761: It would be nice to define regs as `Box<Option<Registers>>`
+// since the registers are sometimes empty, but the discriminant would
// then misalign the regs again.
pub struct Context {
/// Hold the registers while the task or scheduler is suspended
- regs: ~Registers,
+ regs: Box<Registers>,
/// Lower bound and upper bound for the stack
stack_bounds: Option<(uint, uint)>,
}
pub fn swap(out_context: &mut Context, in_context: &Context) {
rtdebug!("swapping contexts");
let out_regs: &mut Registers = match out_context {
- &Context { regs: ~ref mut r, .. } => r
+ &Context { regs: box ref mut r, .. } => r
};
let in_regs: &Registers = match in_context {
- &Context { regs: ~ref r, .. } => r
+ &Context { regs: box ref r, .. } => r
};
rtdebug!("noting the stack limit and doing raw swap");
}
#[cfg(target_arch = "x86")]
-fn new_regs() -> ~Registers {
+fn new_regs() -> Box<Registers> {
box Registers {
eax: 0, ebx: 0, ecx: 0, edx: 0,
ebp: 0, esi: 0, edi: 0, esp: 0,
type Registers = [uint, ..22];
#[cfg(windows, target_arch = "x86_64")]
-fn new_regs() -> ~Registers { box [0, .. 34] }
+fn new_regs() -> Box<Registers> { box [0, .. 34] }
#[cfg(not(windows), target_arch = "x86_64")]
-fn new_regs() -> ~Registers { box {let v = [0, .. 22]; v} }
+fn new_regs() -> Box<Registers> { box {let v = [0, .. 22]; v} }
#[cfg(target_arch = "x86_64")]
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
type Registers = [uint, ..32];
#[cfg(target_arch = "arm")]
-fn new_regs() -> ~Registers { box {[0, .. 32]} }
+fn new_regs() -> Box<Registers> { box {[0, .. 32]} }
#[cfg(target_arch = "arm")]
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
type Registers = [uint, ..32];
#[cfg(target_arch = "mips")]
-fn new_regs() -> ~Registers { box [0, .. 32] }
+fn new_regs() -> Box<Registers> { box [0, .. 32] }
#[cfg(target_arch = "mips")]
fn initialize_call_frame(regs: &mut Registers, fptr: InitFn, arg: uint,
/// The return value is used as the process return code. 0 on success, 101 on
/// error.
pub fn start(argc: int, argv: **u8,
- event_loop_factory: fn() -> ~rtio::EventLoop:Send,
+ event_loop_factory: fn() -> Box<rtio::EventLoop:Send>,
main: proc():Send) -> int {
rt::init(argc, argv);
let mut main = Some(main);
///
/// This function will not return until all schedulers in the associated pool
/// have returned.
-pub fn run(event_loop_factory: fn() -> ~rtio::EventLoop:Send,
+pub fn run(event_loop_factory: fn() -> Box<rtio::EventLoop:Send>,
main: proc():Send) -> int {
// Create a scheduler pool and spawn the main task into this pool. We will
// get notified over a channel when the main task exits.
pub threads: uint,
/// A factory function used to create new event loops. If this is not
/// specified then the default event loop factory is used.
- pub event_loop_factory: fn() -> ~rtio::EventLoop:Send,
+ pub event_loop_factory: fn() -> Box<rtio::EventLoop:Send>,
}
impl PoolConfig {
id: uint,
threads: Vec<Thread<()>>,
handles: Vec<SchedHandle>,
- stealers: Vec<deque::Stealer<~task::GreenTask>>,
+ stealers: Vec<deque::Stealer<Box<task::GreenTask>>>,
next_friend: uint,
stack_pool: StackPool,
- deque_pool: deque::BufferPool<~task::GreenTask>,
+ deque_pool: deque::BufferPool<Box<task::GreenTask>>,
sleepers: SleeperList,
- factory: fn() -> ~rtio::EventLoop:Send,
+ factory: fn() -> Box<rtio::EventLoop:Send>,
task_state: TaskState,
tasks_done: Receiver<()>,
}
/// This is useful to create a task which can then be sent to a specific
/// scheduler created by `spawn_sched` (and possibly pin it to that
/// scheduler).
- pub fn task(&mut self, opts: TaskOpts, f: proc():Send) -> ~GreenTask {
+ pub fn task(&mut self, opts: TaskOpts, f: proc():Send) -> Box<GreenTask> {
GreenTask::configure(&mut self.stack_pool, opts, f)
}
/// inside this pool of schedulers
pub task_state: TaskState,
/// There are N work queues, one per scheduler.
- work_queue: deque::Worker<~GreenTask>,
+ work_queue: deque::Worker<Box<GreenTask>>,
/// Work queues for the other schedulers. These are created by
/// cloning the core work queues.
- work_queues: Vec<deque::Stealer<~GreenTask>>,
+ work_queues: Vec<deque::Stealer<Box<GreenTask>>>,
/// The queue of incoming messages from other schedulers.
/// These are enqueued by SchedHandles after which a remote callback
/// is triggered to handle the message.
no_sleep: bool,
/// The scheduler runs on a special task. When it is not running
/// it is stored here instead of the work queue.
- sched_task: Option<~GreenTask>,
+ sched_task: Option<Box<GreenTask>>,
/// An action performed after a context switch on behalf of the
/// code running before the context switch
cleanup_job: Option<CleanupJob>,
/// A fast XorShift rng for scheduler use
rng: XorShiftRng,
/// A togglable idle callback
- idle_callback: Option<~PausableIdleCallback:Send>,
+ idle_callback: Option<Box<PausableIdleCallback:Send>>,
/// A countdown that starts at a random value and is decremented
/// every time a yield check is performed. When it hits 0 a task
/// will yield.
// destroyed before it's actually destroyed.
/// The event loop used to drive the scheduler and perform I/O
- pub event_loop: ~EventLoop:Send,
+ pub event_loop: Box<EventLoop:Send>,
}
/// An indication of how hard to work on a given operation, the difference
// * Initialization Functions
pub fn new(pool_id: uint,
- event_loop: ~EventLoop:Send,
- work_queue: deque::Worker<~GreenTask>,
- work_queues: Vec<deque::Stealer<~GreenTask>>,
+ event_loop: Box<EventLoop:Send>,
+ work_queue: deque::Worker<Box<GreenTask>>,
+ work_queues: Vec<deque::Stealer<Box<GreenTask>>>,
sleeper_list: SleeperList,
state: TaskState)
-> Scheduler {
}
pub fn new_special(pool_id: uint,
- event_loop: ~EventLoop:Send,
- work_queue: deque::Worker<~GreenTask>,
- work_queues: Vec<deque::Stealer<~GreenTask>>,
+ event_loop: Box<EventLoop:Send>,
+ work_queue: deque::Worker<Box<GreenTask>>,
+ work_queues: Vec<deque::Stealer<Box<GreenTask>>>,
sleeper_list: SleeperList,
run_anything: bool,
friend: Option<SchedHandle>,
pub fn bootstrap(mut ~self) {
// Build an Idle callback.
- let cb = box SchedRunner as ~Callback:Send;
+ let cb = box SchedRunner as Box<Callback:Send>;
self.idle_callback = Some(self.event_loop.pausable_idle_callback(cb));
// Create a task for the scheduler with an empty context.
// This does not return a scheduler, as the scheduler is placed
// inside the task.
- pub fn run(mut ~self, stask: ~GreenTask) -> ~GreenTask {
+ pub fn run(mut ~self, stask: Box<GreenTask>) -> Box<GreenTask> {
// This is unsafe because we need to place the scheduler, with
// the event_loop inside, inside our task. But we still need a
// mutable reference to the event_loop to give it the "run"
// command.
unsafe {
- let event_loop: *mut ~EventLoop:Send = &mut self.event_loop;
+ let event_loop: *mut Box<EventLoop:Send> = &mut self.event_loop;
// Our scheduler must be in the task before the event loop
// is started.
stask.put_with_sched(self);
// If we try really hard to do some work, but no work is available to be
// done, then we fall back to epoll() to block this thread waiting for more
// work (instead of busy waiting).
- fn run_sched_once(mut ~self, stask: ~GreenTask) {
+ fn run_sched_once(mut ~self, stask: Box<GreenTask>) {
// Make sure that we're not lying in that the `stask` argument is indeed
// the scheduler task for this scheduler.
assert!(self.sched_task.is_none());
// returns the still-available scheduler. At this point all
// message-handling will count as a turn of work, and as a result
// return None.
- fn interpret_message_queue(mut ~self, stask: ~GreenTask,
+ fn interpret_message_queue(mut ~self, stask: Box<GreenTask>,
effort: EffortLevel)
- -> (~Scheduler, ~GreenTask, bool)
+ -> (Box<Scheduler>, Box<GreenTask>, bool)
{
let msg = if effort == DontTryTooHard {
}
}
- fn do_work(mut ~self,
- stask: ~GreenTask) -> (~Scheduler, ~GreenTask, bool) {
+ fn do_work(mut ~self, stask: Box<GreenTask>)
+ -> (Box<Scheduler>, Box<GreenTask>, bool) {
rtdebug!("scheduler calling do work");
match self.find_work() {
Some(task) => {
// First step in the process is to find a task. This function does
// that by first checking the local queue, and if there is no work
// there, trying to steal from the remote work queues.
- fn find_work(&mut self) -> Option<~GreenTask> {
+ fn find_work(&mut self) -> Option<Box<GreenTask>> {
rtdebug!("scheduler looking for work");
if !self.steal_for_yield {
match self.work_queue.pop() {
// Try stealing from all queues the scheduler knows about. This
// naive implementation can steal from our own queue or from other
// special schedulers.
- fn try_steals(&mut self) -> Option<~GreenTask> {
+ fn try_steals(&mut self) -> Option<Box<GreenTask>> {
let work_queues = &mut self.work_queues;
let len = work_queues.len();
let start_index = self.rng.gen_range(0, len);
// * Task Routing Functions - Make sure tasks send up in the right
// place.
- fn process_task(mut ~self, cur: ~GreenTask,
- mut next: ~GreenTask,
- schedule_fn: SchedulingFn) -> (~Scheduler, ~GreenTask) {
+ fn process_task(mut ~self,
+ cur: Box<GreenTask>,
+ mut next: Box<GreenTask>,
+ schedule_fn: SchedulingFn)
+ -> (Box<Scheduler>, Box<GreenTask>) {
rtdebug!("processing a task");
match next.take_unwrap_home() {
}
}
- fn send_task_home(task: ~GreenTask) {
+ fn send_task_home(task: Box<GreenTask>) {
let mut task = task;
match task.take_unwrap_home() {
HomeSched(mut home_handle) => home_handle.send(PinnedTask(task)),
/// Take a non-homed task we aren't allowed to run here and send
/// it to the designated friend scheduler to execute.
- fn send_to_friend(&mut self, task: ~GreenTask) {
+ fn send_to_friend(&mut self, task: Box<GreenTask>) {
rtdebug!("sending a task to friend");
match self.friend_handle {
Some(ref mut handle) => {
/// Pushes the task onto the work stealing queue and tells the
/// event loop to run it later. Always use this instead of pushing
/// to the work queue directly.
- pub fn enqueue_task(&mut self, task: ~GreenTask) {
+ pub fn enqueue_task(&mut self, task: Box<GreenTask>) {
// We push the task onto our local queue clone.
assert!(!task.is_sched());
// old task as inputs.
pub fn change_task_context(mut ~self,
- current_task: ~GreenTask,
- mut next_task: ~GreenTask,
- f: |&mut Scheduler, ~GreenTask|) -> ~GreenTask {
+ current_task: Box<GreenTask>,
+ mut next_task: Box<GreenTask>,
+ f: |&mut Scheduler, Box<GreenTask>|)
+ -> Box<GreenTask> {
let f_opaque = ClosureConverter::from_fn(f);
let current_task_dupe = &*current_task as *GreenTask;
// When the context swaps back to this task we immediately
// run the cleanup job, as expected by the previously called
// swap_contexts function.
- let mut current_task: ~GreenTask = unsafe {
+ let mut current_task: Box<GreenTask> = unsafe {
cast::transmute(current_task_dupe)
};
current_task.sched.get_mut_ref().run_cleanup_job();
// * Context Swapping Helpers - Here be ugliness!
- pub fn resume_task_immediately(~self, cur: ~GreenTask,
- next: ~GreenTask) -> (~Scheduler, ~GreenTask) {
+ pub fn resume_task_immediately(~self,
+ cur: Box<GreenTask>,
+ next: Box<GreenTask>)
+ -> (Box<Scheduler>, Box<GreenTask>) {
assert!(cur.is_sched());
let mut cur = self.change_task_context(cur, next, |sched, stask| {
assert!(sched.sched_task.is_none());
(cur.sched.take_unwrap(), cur)
}
- fn resume_task_immediately_cl(sched: ~Scheduler,
- cur: ~GreenTask,
- next: ~GreenTask) -> (~Scheduler, ~GreenTask) {
+ fn resume_task_immediately_cl(sched: Box<Scheduler>,
+ cur: Box<GreenTask>,
+ next: Box<GreenTask>)
+ -> (Box<Scheduler>, Box<GreenTask>) {
sched.resume_task_immediately(cur, next)
}
/// guaranteed that this function will not return before the given closure
/// has returned.
pub fn deschedule_running_task_and_then(mut ~self,
- cur: ~GreenTask,
+ cur: Box<GreenTask>,
f: |&mut Scheduler, BlockedTask|) {
// Trickier - we need to get the scheduler task out of self
// and use it as the destination.
}
pub fn switch_running_tasks_and_then(~self,
- cur: ~GreenTask,
- next: ~GreenTask,
+ cur: Box<GreenTask>,
+ next: Box<GreenTask>,
f: |&mut Scheduler, BlockedTask|) {
// And here comes one of the sad moments in which a lock is used in a
// core portion of the rust runtime. As always, this is highly
cur.put();
}
- fn switch_task(sched: ~Scheduler, cur: ~GreenTask,
- next: ~GreenTask) -> (~Scheduler, ~GreenTask) {
+ fn switch_task(sched: Box<Scheduler>,
+ cur: Box<GreenTask>,
+ next: Box<GreenTask>)
+ -> (Box<Scheduler>, Box<GreenTask>) {
let mut cur = sched.change_task_context(cur, next, |sched, last_task| {
if last_task.is_sched() {
assert!(sched.sched_task.is_none());
/// Called by a running task to end execution, after which it will
/// be recycled by the scheduler for reuse in a new task.
- pub fn terminate_current_task(mut ~self, cur: ~GreenTask) -> ! {
+ pub fn terminate_current_task(mut ~self, cur: Box<GreenTask>) -> ! {
// Similar to deschedule running task and then, but cannot go through
// the task-blocking path. The task is already dying.
let stask = self.sched_task.take_unwrap();
fail!("should never return!");
}
- pub fn run_task(~self, cur: ~GreenTask, next: ~GreenTask) {
+ pub fn run_task(~self, cur: Box<GreenTask>, next: Box<GreenTask>) {
let (sched, task) =
self.process_task(cur, next, Scheduler::switch_task);
task.put_with_sched(sched);
}
- pub fn run_task_later(mut cur: ~GreenTask, next: ~GreenTask) {
+ pub fn run_task_later(mut cur: Box<GreenTask>, next: Box<GreenTask>) {
let mut sched = cur.sched.take_unwrap();
sched.enqueue_task(next);
cur.put_with_sched(sched);
/// to introduce some amount of randomness to the scheduler. Currently the
/// randomness is a result of performing a round of work stealing (which
/// may end up stealing from the current scheduler).
- pub fn yield_now(mut ~self, cur: ~GreenTask) {
+ pub fn yield_now(mut ~self, cur: Box<GreenTask>) {
// Async handles trigger the scheduler by calling yield_now on the local
// task, which eventually gets us to here. See comments in SchedRunner
// for more info on this.
}
}
- pub fn maybe_yield(mut ~self, cur: ~GreenTask) {
+ pub fn maybe_yield(mut ~self, cur: Box<GreenTask>) {
// It's possible for sched tasks to possibly call this function, and it
// just means that they're likely sending on channels (which
// occasionally call this function). Sched tasks follow different paths
// Supporting types
-type SchedulingFn = fn (~Scheduler, ~GreenTask, ~GreenTask)
- -> (~Scheduler, ~GreenTask);
+type SchedulingFn = fn(Box<Scheduler>, Box<GreenTask>, Box<GreenTask>)
+ -> (Box<Scheduler>, Box<GreenTask>);
pub enum SchedMessage {
Wake,
Shutdown,
- NewNeighbor(deque::Stealer<~GreenTask>),
- PinnedTask(~GreenTask),
- TaskFromFriend(~GreenTask),
- RunOnce(~GreenTask),
+ NewNeighbor(deque::Stealer<Box<GreenTask>>),
+ PinnedTask(Box<GreenTask>),
+ TaskFromFriend(Box<GreenTask>),
+ RunOnce(Box<GreenTask>),
}
pub struct SchedHandle {
- remote: ~RemoteCallback:Send,
+ remote: Box<RemoteCallback:Send>,
queue: msgq::Producer<SchedMessage>,
pub sched_id: uint
}
// This function could be converted to `GreenTask::convert` if
// absolutely necessary, but for cleanliness it is much better to not
// use the conversion function.
- let task: ~Task = Local::take();
+ let task: Box<Task> = Local::take();
task.yield_now();
}
}
struct CleanupJob {
- task: ~GreenTask,
+ task: Box<GreenTask>,
f: UnsafeTaskReceiver
}
impl CleanupJob {
- pub fn new(task: ~GreenTask, f: UnsafeTaskReceiver) -> CleanupJob {
+ pub fn new(task: Box<GreenTask>, f: UnsafeTaskReceiver) -> CleanupJob {
CleanupJob {
task: task,
f: f
// complaining
type UnsafeTaskReceiver = raw::Closure;
trait ClosureConverter {
- fn from_fn(|&mut Scheduler, ~GreenTask|) -> Self;
- fn to_fn(self) -> |&mut Scheduler, ~GreenTask|;
+ fn from_fn(|&mut Scheduler, Box<GreenTask>|) -> Self;
+ fn to_fn(self) -> |&mut Scheduler, Box<GreenTask>|;
}
impl ClosureConverter for UnsafeTaskReceiver {
- fn from_fn(f: |&mut Scheduler, ~GreenTask|) -> UnsafeTaskReceiver {
+ fn from_fn(f: |&mut Scheduler, Box<GreenTask>|) -> UnsafeTaskReceiver {
unsafe { cast::transmute(f) }
}
- fn to_fn(self) -> |&mut Scheduler, ~GreenTask| {
+ fn to_fn(self) -> |&mut Scheduler, Box<GreenTask>| {
unsafe { cast::transmute(self) }
}
}
// Signal from the special task that we are done.
let (tx, rx) = channel::<()>();
- fn run(next: ~GreenTask) {
+ fn run(next: Box<GreenTask>) {
let mut task = GreenTask::convert(Local::take());
let sched = task.sched.take_unwrap();
sched.run_task(task, next)
impl Runtime for SimpleTask {
// Implement the simple tasks of descheduling and rescheduling, but only in
// a simple number of cases.
- fn deschedule(mut ~self, times: uint, mut cur_task: ~Task,
+ fn deschedule(mut ~self, times: uint, mut cur_task: Box<Task>,
f: |BlockedTask| -> Result<(), BlockedTask>) {
assert!(times == 1);
}
Local::put(cur_task);
}
- fn reawaken(mut ~self, mut to_wake: ~Task) {
+ fn reawaken(mut ~self, mut to_wake: Box<Task>) {
let me = &mut *self as *mut SimpleTask;
to_wake.put_runtime(self);
unsafe {
// purpose. A "simple task" is just that, a very simple task that can't
// really do a whole lot. The only purpose of the task is to get us off our
// feet and running.
- fn yield_now(~self, _cur_task: ~Task) { fail!() }
- fn maybe_yield(~self, _cur_task: ~Task) { fail!() }
- fn spawn_sibling(~self, _cur_task: ~Task, _opts: TaskOpts, _f: proc():Send) {
+ fn yield_now(~self, _cur_task: Box<Task>) { fail!() }
+ fn maybe_yield(~self, _cur_task: Box<Task>) { fail!() }
+ fn spawn_sibling(~self,
+ _cur_task: Box<Task>,
+ _opts: TaskOpts,
+ _f: proc():Send) {
fail!()
}
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> { None }
fn stack_bounds(&self) -> (uint, uint) { fail!() }
fn can_block(&self) -> bool { true }
- fn wrap(~self) -> ~Any { fail!() }
+ fn wrap(~self) -> Box<Any> { fail!() }
}
-pub fn task() -> ~Task {
+pub fn task() -> Box<Task> {
let mut task = box Task::new();
task.put_runtime(box SimpleTask {
lock: unsafe {NativeMutex::new()},
/// Slot for maintaining ownership of a scheduler. If a task is running,
/// this value will be Some(sched) where the task is running on "sched".
- pub sched: Option<~Scheduler>,
+ pub sched: Option<Box<Scheduler>>,
/// Temporary ownership slot of a std::rt::task::Task object. This is used
/// to squirrel that libstd task away while we're performing green task
/// operations.
- pub task: Option<~Task>,
+ pub task: Option<Box<Task>>,
/// Dictates whether this is a sched task or a normal green task
pub task_type: TaskType,
/// for all green tasks. This code is actually called after the initial context
/// switch onto a green thread.
///
-/// The first argument to this function is the `~GreenTask` pointer, and the
-/// next two arguments are the user-provided procedure for running code.
+/// The first argument to this function is the `Box<GreenTask>` pointer, and
+/// the next two arguments are the user-provided procedure for running code.
///
/// The goal for having this weird-looking function is to reduce the number of
/// allocations done on a green-task startup as much as possible.
cast::transmute(raw::Procedure { code: code, env: env })
};
- // Acquire ownership of the `~GreenTask`
- let mut task: ~GreenTask = unsafe { cast::transmute(task) };
+ // Acquire ownership of the `Box<GreenTask>`
+ let mut task: Box<GreenTask> = unsafe { cast::transmute(task) };
// First code after swap to this new context. Run our cleanup job
task.pool_id = {
/// and will not have any contained Task structure.
pub fn new(stack_pool: &mut StackPool,
stack_size: Option<uint>,
- start: proc():Send) -> ~GreenTask {
+ start: proc():Send) -> Box<GreenTask> {
GreenTask::new_homed(stack_pool, stack_size, AnySched, start)
}
pub fn new_homed(stack_pool: &mut StackPool,
stack_size: Option<uint>,
home: Home,
- start: proc():Send) -> ~GreenTask {
+ start: proc():Send) -> Box<GreenTask> {
// Allocate ourselves a GreenTask structure
let mut ops = GreenTask::new_typed(None, TypeGreen(Some(home)));
/// Creates a new green task with the specified coroutine and type, this is
/// useful when creating scheduler tasks.
pub fn new_typed(coroutine: Option<Coroutine>,
- task_type: TaskType) -> ~GreenTask {
+ task_type: TaskType) -> Box<GreenTask> {
box GreenTask {
pool_id: 0,
coroutine: coroutine,
/// new stack for this task.
pub fn configure(pool: &mut StackPool,
opts: TaskOpts,
- f: proc():Send) -> ~GreenTask {
+ f: proc():Send) -> Box<GreenTask> {
let TaskOpts {
notify_chan, name, stack_size,
stderr, stdout,
///
/// This function will assert that the task is indeed a green task before
/// returning (and will kill the entire process if this is wrong).
- pub fn convert(mut task: ~Task) -> ~GreenTask {
+ pub fn convert(mut task: Box<Task>) -> Box<GreenTask> {
match task.maybe_take_runtime::<GreenTask>() {
Some(mut green) => {
green.put_task(task);
self as *GreenTask as uint
}
- pub unsafe fn from_uint(val: uint) -> ~GreenTask { cast::transmute(val) }
+ pub unsafe fn from_uint(val: uint) -> Box<GreenTask> {
+ cast::transmute(val)
+ }
// Runtime glue functions and helpers
- pub fn put_with_sched(mut ~self, sched: ~Scheduler) {
+ pub fn put_with_sched(mut ~self, sched: Box<Scheduler>) {
assert!(self.sched.is_none());
self.sched = Some(sched);
self.put();
}
- pub fn put_task(&mut self, task: ~Task) {
+ pub fn put_task(&mut self, task: Box<Task>) {
assert!(self.task.is_none());
self.task = Some(task);
}
- pub fn swap(mut ~self) -> ~Task {
+ pub fn swap(mut ~self) -> Box<Task> {
let mut task = self.task.take_unwrap();
task.put_runtime(self);
return task;
}
impl Runtime for GreenTask {
- fn yield_now(mut ~self, cur_task: ~Task) {
+ fn yield_now(mut ~self, cur_task: Box<Task>) {
self.put_task(cur_task);
let sched = self.sched.take_unwrap();
sched.yield_now(self);
}
- fn maybe_yield(mut ~self, cur_task: ~Task) {
+ fn maybe_yield(mut ~self, cur_task: Box<Task>) {
self.put_task(cur_task);
let sched = self.sched.take_unwrap();
sched.maybe_yield(self);
}
- fn deschedule(mut ~self, times: uint, cur_task: ~Task,
+ fn deschedule(mut ~self, times: uint, cur_task: Box<Task>,
f: |BlockedTask| -> Result<(), BlockedTask>) {
self.put_task(cur_task);
let mut sched = self.sched.take_unwrap();
}
}
- fn reawaken(mut ~self, to_wake: ~Task) {
+ fn reawaken(mut ~self, to_wake: Box<Task>) {
self.put_task(to_wake);
assert!(self.sched.is_none());
// Optimistically look for a local task, but if one's not available to
// inspect (in order to see if it's in the same sched pool as we are),
// then just use our remote wakeup routine and carry on!
- let mut running_task: ~Task = match Local::try_take() {
+ let mut running_task: Box<Task> = match Local::try_take() {
Some(task) => task,
None => return self.reawaken_remotely()
};
}
}
- fn spawn_sibling(mut ~self, cur_task: ~Task, opts: TaskOpts, f: proc():Send) {
+ fn spawn_sibling(mut ~self,
+ cur_task: Box<Task>,
+ opts: TaskOpts,
+ f: proc():Send) {
self.put_task(cur_task);
// Spawns a task into the current scheduler. We allocate the new task's
fn can_block(&self) -> bool { false }
- fn wrap(~self) -> ~Any { self as ~Any }
+ fn wrap(~self) -> Box<Any> { self as Box<Any> }
}
#[cfg(test)]
let (tx, rx) = channel();
spawn_opts(TaskOpts::new(), proc() {
spawn(proc() {
- let mut task: ~Task = Local::take();
+ let mut task: Box<Task> = Local::take();
match task.maybe_take_runtime::<GreenTask>() {
Some(ops) => {
task.put_runtime(ops);
fn main() {
let val = hexfloat!("0x1.ffffb4", f32);
}
- ```
+```
# References
#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
register(token::intern("hexfloat"),
- NormalTT(~BasicMacroExpander {
+ NormalTT(box BasicMacroExpander {
expander: expand_syntax_ext,
span: None,
},
}
}
-pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
+pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+ -> Box<base::MacResult> {
let (expr, ty_lit) = parse_tts(cx, tts);
let ty = match ty_lit {
/// Error log level
pub static ERROR: u32 = 1;
-local_data_key!(local_logger: ~Logger:Send)
+local_data_key!(local_logger: Box<Logger:Send>)
/// 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
impl Logger for DefaultLogger {
fn log(&mut self, record: &LogRecord) {
- match write!(&mut self.handle,
- "{}:{}: {}",
- record.level,
- record.module_path,
- record.args) {
+ match writeln!(&mut self.handle,
+ "{}:{}: {}",
+ record.level,
+ record.module_path,
+ record.args) {
Err(e) => fail!("failed to log: {}", e),
Ok(()) => {}
}
// 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(|| {
- box DefaultLogger { handle: io::stderr() } as ~Logger:Send
+ box DefaultLogger { handle: io::stderr() } as Box<Logger:Send>
});
logger.log(&LogRecord {
level: LogLevel(level),
/// Replaces the task-local logger with the specified logger, returning the old
/// logger.
-pub fn set_logger(logger: ~Logger:Send) -> Option<~Logger:Send> {
+pub fn set_logger(logger: Box<Logger:Send>) -> Option<Box<Logger:Send>> {
let prev = local_data::pop(local_logger);
local_data::set(local_logger, logger);
return prev;
// Schedule the cleanup for this global for when the runtime exits.
rt::at_exit(proc() {
assert!(!DIRECTIVES.is_null());
- let _directives: ~Vec<directive::LogDirective> =
+ let _directives: Box<Vec<directive::LogDirective>> =
cast::transmute(DIRECTIVES);
DIRECTIVES = 0 as *Vec<directive::LogDirective>;
});
//! Blocking posix-based file I/O
+use libc::{c_int, c_void};
+use libc;
use std::sync::arc::UnsafeArc;
use std::c_str::CString;
use std::io::IoError;
use std::io;
-use libc::{c_int, c_void};
-use libc;
use std::mem;
use std::rt::rtio;
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
self.inner_write(buf)
}
- fn clone(&self) -> ~rtio::RtioPipe:Send {
- box FileDesc { inner: self.inner.clone() } as ~rtio::RtioPipe:Send
+ fn clone(&self) -> Box<rtio::RtioPipe:Send> {
+ box FileDesc { inner: self.inner.clone() } as Box<rtio::RtioPipe:Send>
}
}
pub fn mkdir(p: &CString, mode: io::FilePermission) -> IoResult<()> {
super::mkerr_libc(retry(|| unsafe {
- libc::mkdir(p.with_ref(|p| p), mode as libc::mode_t)
+ libc::mkdir(p.with_ref(|p| p), mode.bits() as libc::mode_t)
}))
}
pub fn chmod(p: &CString, mode: io::FilePermission) -> IoResult<()> {
super::mkerr_libc(retry(|| unsafe {
- libc::chmod(p.with_ref(|p| p), mode as libc::mode_t)
+ libc::chmod(p.with_ref(|p| p), mode.bits() as libc::mode_t)
}))
}
path: Path::new(path),
size: stat.st_size as u64,
kind: kind,
- perm: (stat.st_mode) as io::FilePermission & io::AllPermissions,
+ perm: unsafe {
+ io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
+ },
created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64),
accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64),
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
self.inner_write(buf)
}
- fn clone(&self) -> ~rtio::RtioPipe:Send {
- box FileDesc { inner: self.inner.clone() } as ~rtio::RtioPipe:Send
+ fn clone(&self) -> Box<rtio::RtioPipe:Send> {
+ box FileDesc { inner: self.inner.clone() } as Box<rtio::RtioPipe:Send>
}
}
pub fn chmod(p: &CString, mode: io::FilePermission) -> IoResult<()> {
super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
- libc::wchmod(p, mode as libc::c_int)
+ libc::wchmod(p, mode.bits() as libc::c_int)
}))
}
path: Path::new(path),
size: stat.st_size as u64,
kind: kind,
- perm: (stat.st_mode) as io::FilePermission & io::AllPermissions,
+ perm: unsafe {
+ io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
+ },
created: stat.st_ctime as u64,
modified: stat.st_mtime as u64,
accessed: stat.st_atime as u64,
//! play. The only dependencies of these modules are the normal system libraries
//! that you would find on the respective platform.
+use libc::c_int;
+use libc;
use std::c_str::CString;
use std::io;
use std::io::IoError;
use std::io::net::ip::SocketAddr;
use std::io::process::ProcessConfig;
use std::io::signal::Signum;
-use libc::c_int;
-use libc;
use std::os;
use std::rt::rtio;
-use std::rt::rtio::{RtioTcpStream, RtioTcpListener, RtioUdpSocket,
- RtioUnixListener, RtioPipe, RtioFileStream, RtioProcess,
- RtioSignal, RtioTTY, CloseBehavior, RtioTimer};
+use std::rt::rtio::{RtioTcpStream, RtioTcpListener, RtioUdpSocket};
+use std::rt::rtio::{RtioUnixListener, RtioPipe, RtioFileStream, RtioProcess};
+use std::rt::rtio::{RtioSignal, RtioTTY, CloseBehavior, RtioTimer};
use ai = std::io::net::addrinfo;
// Local re-exports
impl rtio::IoFactory for IoFactory {
// networking
fn tcp_connect(&mut self, addr: SocketAddr,
- timeout: Option<u64>) -> IoResult<~RtioTcpStream:Send> {
- net::TcpStream::connect(addr, timeout).map(|s| box s as ~RtioTcpStream:Send)
+ timeout: Option<u64>) -> IoResult<Box<RtioTcpStream:Send>> {
+ net::TcpStream::connect(addr, timeout).map(|s| {
+ box s as Box<RtioTcpStream:Send>
+ })
}
- fn tcp_bind(&mut self, addr: SocketAddr) -> IoResult<~RtioTcpListener:Send> {
- net::TcpListener::bind(addr).map(|s| box s as ~RtioTcpListener:Send)
+ fn tcp_bind(&mut self, addr: SocketAddr)
+ -> IoResult<Box<RtioTcpListener:Send>> {
+ net::TcpListener::bind(addr).map(|s| {
+ box s as Box<RtioTcpListener:Send>
+ })
}
- fn udp_bind(&mut self, addr: SocketAddr) -> IoResult<~RtioUdpSocket:Send> {
- net::UdpSocket::bind(addr).map(|u| box u as ~RtioUdpSocket:Send)
+ fn udp_bind(&mut self, addr: SocketAddr)
+ -> IoResult<Box<RtioUdpSocket:Send>> {
+ net::UdpSocket::bind(addr).map(|u| box u as Box<RtioUdpSocket:Send>)
}
- fn unix_bind(&mut self, path: &CString) -> IoResult<~RtioUnixListener:Send> {
- pipe::UnixListener::bind(path).map(|s| box s as ~RtioUnixListener:Send)
+ fn unix_bind(&mut self, path: &CString)
+ -> IoResult<Box<RtioUnixListener:Send>> {
+ pipe::UnixListener::bind(path).map(|s| {
+ box s as Box<RtioUnixListener:Send>
+ })
}
fn unix_connect(&mut self, path: &CString,
- timeout: Option<u64>) -> IoResult<~RtioPipe:Send> {
- pipe::UnixStream::connect(path, timeout).map(|s| box s as ~RtioPipe:Send)
+ timeout: Option<u64>) -> IoResult<Box<RtioPipe:Send>> {
+ pipe::UnixStream::connect(path, timeout).map(|s| {
+ box s as Box<RtioPipe:Send>
+ })
}
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
hint: Option<ai::Hint>) -> IoResult<~[ai::Info]> {
}
// filesystem operations
- fn fs_from_raw_fd(&mut self, fd: c_int,
- close: CloseBehavior) -> ~RtioFileStream:Send {
+ fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior)
+ -> Box<RtioFileStream:Send> {
let close = match close {
rtio::CloseSynchronously | rtio::CloseAsynchronously => true,
rtio::DontClose => false
};
- box file::FileDesc::new(fd, close) as ~RtioFileStream:Send
+ box file::FileDesc::new(fd, close) as Box<RtioFileStream:Send>
}
fn fs_open(&mut self, path: &CString, fm: io::FileMode, fa: io::FileAccess)
- -> IoResult<~RtioFileStream:Send> {
- file::open(path, fm, fa).map(|fd| box fd as ~RtioFileStream:Send)
+ -> IoResult<Box<RtioFileStream:Send>> {
+ file::open(path, fm, fa).map(|fd| box fd as Box<RtioFileStream:Send>)
}
fn fs_unlink(&mut self, path: &CString) -> IoResult<()> {
file::unlink(path)
}
// misc
- fn timer_init(&mut self) -> IoResult<~RtioTimer:Send> {
- timer::Timer::new().map(|t| box t as ~RtioTimer:Send)
+ fn timer_init(&mut self) -> IoResult<Box<RtioTimer:Send>> {
+ timer::Timer::new().map(|t| box t as Box<RtioTimer:Send>)
}
fn spawn(&mut self, config: ProcessConfig)
- -> IoResult<(~RtioProcess:Send, ~[Option<~RtioPipe:Send>])> {
+ -> IoResult<(Box<RtioProcess:Send>,
+ ~[Option<Box<RtioPipe:Send>>])> {
process::Process::spawn(config).map(|(p, io)| {
- (box p as ~RtioProcess:Send,
- io.move_iter().map(|p| p.map(|p| box p as ~RtioPipe:Send)).collect())
+ (box p as Box<RtioProcess:Send>,
+ io.move_iter().map(|p| p.map(|p| {
+ box p as Box<RtioPipe:Send>
+ })).collect())
})
}
fn kill(&mut self, pid: libc::pid_t, signum: int) -> IoResult<()> {
process::Process::kill(pid, signum)
}
- fn pipe_open(&mut self, fd: c_int) -> IoResult<~RtioPipe:Send> {
- Ok(box file::FileDesc::new(fd, true) as ~RtioPipe:Send)
+ fn pipe_open(&mut self, fd: c_int) -> IoResult<Box<RtioPipe:Send>> {
+ Ok(box file::FileDesc::new(fd, true) as Box<RtioPipe:Send>)
}
fn tty_open(&mut self, fd: c_int, _readable: bool)
- -> IoResult<~RtioTTY:Send>
- {
+ -> IoResult<Box<RtioTTY:Send>> {
if unsafe { libc::isatty(fd) } != 0 {
- Ok(box file::FileDesc::new(fd, true) as ~RtioTTY:Send)
+ Ok(box file::FileDesc::new(fd, true) as Box<RtioTTY:Send>)
} else {
Err(IoError {
kind: io::MismatchedFileTypeForOperation,
}
}
fn signal(&mut self, _signal: Signum, _channel: Sender<Signum>)
- -> IoResult<~RtioSignal:Send> {
+ -> IoResult<Box<RtioSignal:Send>> {
Err(unimpl())
}
}
self.set_keepalive(None)
}
- fn clone(&self) -> ~rtio::RtioTcpStream:Send {
- box TcpStream { inner: self.inner.clone() } as ~rtio::RtioTcpStream:Send
+ fn clone(&self) -> Box<rtio::RtioTcpStream:Send> {
+ box TcpStream {
+ inner: self.inner.clone(),
+ } as Box<rtio::RtioTcpStream:Send>
}
fn close_write(&mut self) -> IoResult<()> {
super::mkerr_libc(unsafe {
}
impl rtio::RtioTcpListener for TcpListener {
- fn listen(~self) -> IoResult<~rtio::RtioTcpAcceptor:Send> {
- self.native_listen(128).map(|a| box a as ~rtio::RtioTcpAcceptor:Send)
+ fn listen(~self) -> IoResult<Box<rtio::RtioTcpAcceptor:Send>> {
+ self.native_listen(128).map(|a| {
+ box a as Box<rtio::RtioTcpAcceptor:Send>
+ })
}
}
}
impl rtio::RtioTcpAcceptor for TcpAcceptor {
- fn accept(&mut self) -> IoResult<~rtio::RtioTcpStream:Send> {
- self.native_accept().map(|s| box s as ~rtio::RtioTcpStream:Send)
+ fn accept(&mut self) -> IoResult<Box<rtio::RtioTcpStream:Send>> {
+ self.native_accept().map(|s| box s as Box<rtio::RtioTcpStream:Send>)
}
fn accept_simultaneously(&mut self) -> IoResult<()> { Ok(()) }
self.set_broadcast(false)
}
- fn clone(&self) -> ~rtio::RtioUdpSocket:Send {
- box UdpSocket { inner: self.inner.clone() } as ~rtio::RtioUdpSocket:Send
+ fn clone(&self) -> Box<rtio::RtioUdpSocket:Send> {
+ box UdpSocket {
+ inner: self.inner.clone(),
+ } as Box<rtio::RtioUdpSocket:Send>
}
}
}
}
- fn clone(&self) -> ~rtio::RtioPipe:Send {
- box UnixStream { inner: self.inner.clone() } as ~rtio::RtioPipe:Send
+ fn clone(&self) -> Box<rtio::RtioPipe:Send> {
+ box UnixStream {
+ inner: self.inner.clone(),
+ } as Box<rtio::RtioPipe:Send>
}
}
}
impl rtio::RtioUnixListener for UnixListener {
- fn listen(~self) -> IoResult<~rtio::RtioUnixAcceptor:Send> {
- self.native_listen(128).map(|a| box a as ~rtio::RtioUnixAcceptor:Send)
+ fn listen(~self) -> IoResult<Box<rtio::RtioUnixAcceptor:Send>> {
+ self.native_listen(128).map(|a| {
+ box a as Box<rtio::RtioUnixAcceptor:Send>
+ })
}
}
}
impl rtio::RtioUnixAcceptor for UnixAcceptor {
- fn accept(&mut self) -> IoResult<~rtio::RtioPipe:Send> {
- self.native_accept().map(|s| box s as ~rtio::RtioPipe:Send)
+ fn accept(&mut self) -> IoResult<Box<rtio::RtioPipe:Send>> {
+ self.native_accept().map(|s| box s as Box<rtio::RtioPipe:Send>)
}
fn set_timeout(&mut self, timeout: Option<u64>) {
self.deadline = timeout.map(|a| ::io::timer::now() + a).unwrap_or(0);
Ok(())
}
- fn clone(&self) -> ~rtio::RtioPipe:Send {
+ fn clone(&self) -> Box<rtio::RtioPipe:Send> {
box UnixStream {
inner: self.inner.clone(),
read: None,
write: None,
- } as ~rtio::RtioPipe:Send
+ } as Box<rtio::RtioPipe:Send>
}
}
}
impl rtio::RtioUnixListener for UnixListener {
- fn listen(~self) -> IoResult<~rtio::RtioUnixAcceptor:Send> {
- self.native_listen().map(|a| box a as ~rtio::RtioUnixAcceptor:Send)
+ fn listen(~self) -> IoResult<Box<rtio::RtioUnixAcceptor:Send>> {
+ self.native_listen().map(|a| {
+ box a as Box<rtio::RtioUnixAcceptor:Send>
+ })
}
}
}
impl rtio::RtioUnixAcceptor for UnixAcceptor {
- fn accept(&mut self) -> IoResult<~rtio::RtioPipe:Send> {
- self.native_accept().map(|s| box s as ~rtio::RtioPipe:Send)
+ fn accept(&mut self) -> IoResult<Box<rtio::RtioPipe:Send>> {
+ self.native_accept().map(|s| box s as Box<rtio::RtioPipe:Send>)
}
fn set_timeout(&mut self, timeout: Option<u64>) {
self.deadline = timeout.map(|i| i + ::io::timer::now()).unwrap_or(0);
// Clean up after ther helper thread
unsafe {
imp::close(HELPER_SIGNAL);
- let _chan: ~Sender<Req> = cast::transmute(HELPER_CHAN);
+ let _chan: Box<Sender<Req>> = cast::transmute(HELPER_CHAN);
HELPER_CHAN = 0 as *mut Sender<Req>;
HELPER_SIGNAL = 0 as imp::signal;
}
pub struct Timer {
id: uint,
- inner: Option<~Inner>,
+ inner: Option<Box<Inner>>,
}
struct Inner {
#[allow(visible_private_types)]
pub enum Req {
// Add a new timer to the helper thread.
- NewTimer(~Inner),
+ NewTimer(Box<Inner>),
// Remove a timer based on its id and then send it back on the channel
// provided
- RemoveTimer(uint, Sender<~Inner>),
+ RemoveTimer(uint, Sender<Box<Inner>>),
// Shut down the loop and then ACK this channel once it's shut down
Shutdown,
// active timers are those which are able to be selected upon (and it's a
// sorted list, and dead timers are those which have expired, but ownership
// hasn't yet been transferred back to the timer itself.
- let mut active: Vec<~Inner> = vec![];
+ let mut active: Vec<Box<Inner>> = vec![];
let mut dead = vec![];
// inserts a timer into an array of timers (sorted by firing time)
- fn insert(t: ~Inner, active: &mut Vec<~Inner>) {
+ fn insert(t: Box<Inner>, active: &mut Vec<Box<Inner>>) {
match active.iter().position(|tm| tm.target > t.target) {
Some(pos) => { active.insert(pos, t); }
None => { active.push(t); }
}
// signals the first requests in the queue, possible re-enqueueing it.
- fn signal(active: &mut Vec<~Inner>, dead: &mut Vec<(uint, ~Inner)>) {
+ fn signal(active: &mut Vec<Box<Inner>>,
+ dead: &mut Vec<(uint, Box<Inner>)>) {
let mut timer = match active.shift() {
Some(timer) => timer, None => return
};
}
}
- fn inner(&mut self) -> ~Inner {
+ fn inner(&mut self) -> Box<Inner> {
match self.inner.take() {
Some(i) => i,
None => {
use task;
/// Creates a new Task which is ready to execute as a 1:1 task.
-pub fn new(stack_bounds: (uint, uint)) -> ~Task {
+pub fn new(stack_bounds: (uint, uint)) -> Box<Task> {
let mut task = box Task::new();
let mut ops = ops();
ops.stack_bounds = stack_bounds;
return task;
}
-fn ops() -> ~Ops {
+fn ops() -> Box<Ops> {
box Ops {
lock: unsafe { NativeMutex::new() },
awoken: false,
}
impl rt::Runtime for Ops {
- fn yield_now(~self, mut cur_task: ~Task) {
+ fn yield_now(~self, mut cur_task: Box<Task>) {
// put the task back in TLS and then invoke the OS thread yield
cur_task.put_runtime(self);
Local::put(cur_task);
Thread::yield_now();
}
- fn maybe_yield(~self, mut cur_task: ~Task) {
+ fn maybe_yield(~self, mut cur_task: Box<Task>) {
// just put the task back in TLS, on OS threads we never need to
// opportunistically yield b/c the OS will do that for us (preemption)
cur_task.put_runtime(self);
Local::put(cur_task);
}
- fn wrap(~self) -> ~Any {
- self as ~Any
+ fn wrap(~self) -> Box<Any> {
+ self as Box<Any>
}
fn stack_bounds(&self) -> (uint, uint) { self.stack_bounds }
// from the wakeup thread back to this thread about the task pointer, and
// there's really no need to. In order to get around this, we cast the task
// to a `uint` which is then used at the end of this function to cast back
- // to a `~Task` object. Naturally, this looks like it violates ownership
- // semantics in that there may be two `~Task` objects.
+ // to a `Box<Task>` object. Naturally, this looks like it violates
+ // ownership semantics in that there may be two `Box<Task>` objects.
//
// The fun part is that the wakeup half of this implementation knows to
// "forget" the task on the other end. This means that the awakening half of
// `awoken` field which indicates whether we were actually woken up via some
// invocation of `reawaken`. This flag is only ever accessed inside the
// lock, so there's no need to make it atomic.
- fn deschedule(mut ~self, times: uint, mut cur_task: ~Task,
+ fn deschedule(mut ~self, times: uint, mut cur_task: Box<Task>,
f: |BlockedTask| -> Result<(), BlockedTask>) {
let me = &mut *self as *mut Ops;
cur_task.put_runtime(self);
// See the comments on `deschedule` for why the task is forgotten here, and
// why it's valid to do so.
- fn reawaken(mut ~self, mut to_wake: ~Task) {
+ fn reawaken(mut ~self, mut to_wake: Box<Task>) {
unsafe {
let me = &mut *self as *mut Ops;
to_wake.put_runtime(self);
}
}
- fn spawn_sibling(~self, mut cur_task: ~Task, opts: TaskOpts, f: proc():Send) {
+ fn spawn_sibling(~self,
+ mut cur_task: Box<Task>,
+ opts: TaskOpts,
+ f: proc():Send) {
cur_task.put_runtime(self);
Local::put(cur_task);
let (tx, rx) = channel();
spawn(proc() {
spawn(proc() {
- let mut task: ~Task = Local::take();
+ let mut task: Box<Task> = Local::take();
match task.maybe_take_runtime::<Ops>() {
Some(ops) => {
task.put_runtime(ops);
```
```rust
-let tuple_ptr = rand::random::<~(f64, char)>();
+let tuple_ptr = rand::random::<Box<(f64, char)>>();
println!("{:?}", tuple_ptr)
```
*/
/// The task-local RNG.
pub struct TaskRng {
// This points into TLS (specifically, it points to the endpoint
- // of a ~ stored in TLS, to make it robust against TLS moving
+ // of a Box stored in TLS, to make it robust against TLS moving
// things internally) and so this struct cannot be legally
// transferred between tasks *and* it's unsafe to deallocate the
// RNG other than when a task is finished.
}
// used to make space in TLS for a random number generator
-local_data_key!(TASK_RNG_KEY: ~TaskRngInner)
+local_data_key!(TASK_RNG_KEY: Box<TaskRngInner>)
/// Retrieve the lazily-initialized task-local random number
/// generator, seeded by the system. Intended to be used in method
let _f : f32 = random();
let _o : Option<Option<i8>> = random();
let _many : ((),
- (~uint, @int, ~Option<~(@u32, ~(@bool,))>),
+ (Box<uint>,
+ @int,
+ Box<Option<Box<(@u32, Box<(@bool,)>)>>>),
(u8, i8, u16, i16, u32, i32, u64, i64),
(f32, (f64, (f64,)))) = random();
}
}
}
-impl<T: Rand> Rand for ~T {
+impl<T: Rand> Rand for Box<T> {
#[inline]
- fn rand<R: Rng>(rng: &mut R) -> ~T { box rng.gen() }
+ fn rand<R: Rng>(rng: &mut R) -> Box<T> { box rng.gen() }
}
impl<T: Rand + 'static> Rand for @T {
Begin(Flags),
End(Flags),
WordBoundary(Flags),
- Capture(uint, Option<~str>, ~Ast),
+ Capture(uint, Option<~str>, Box<Ast>),
// Represent concatenation as a flat vector to avoid blowing the
// stack in the compiler.
Cat(Vec<Ast>),
- Alt(~Ast, ~Ast),
- Rep(~Ast, Repeater, Greed),
+ Alt(Box<Ast>, Box<Ast>),
+ Rep(Box<Ast>, Repeater, Greed),
}
#[deriving(Show, Eq, Clone)]
// alternate and make it a capture.
if cap.is_some() {
let ast = try!(self.pop_ast());
- self.push(Capture(cap.unwrap(), cap_name, ~ast));
+ self.push(Capture(cap.unwrap(), cap_name, box ast));
}
}
'|' => {
_ => {}
}
let greed = try!(self.get_next_greedy());
- self.push(Rep(~ast, rep, greed));
+ self.push(Rep(box ast, rep, greed));
Ok(())
}
let flags = negated | (self.flags & FLAG_NOCASE);
let mut ast = Class(combine_ranges(ranges), flags);
for alt in alts.move_iter() {
- ast = Alt(~alt, ~ast)
+ ast = Alt(box alt, box ast)
}
self.push(ast);
} else if alts.len() > 0 {
let mut ast = alts.pop().unwrap();
for alt in alts.move_iter() {
- ast = Alt(~alt, ~ast)
+ ast = Alt(box alt, box ast)
}
self.push(ast);
}
for _ in iter::range(0, min) {
self.push(ast.clone())
}
- self.push(Rep(~ast, ZeroMore, greed));
+ self.push(Rep(box ast, ZeroMore, greed));
} else {
// Require N copies of what's on the stack and then repeat it
// up to M times optionally.
}
if max.is_some() {
for _ in iter::range(min, max.unwrap()) {
- self.push(Rep(~ast.clone(), ZeroOne, greed))
+ self.push(Rep(box ast.clone(), ZeroOne, greed))
}
}
// It's possible that we popped something off the stack but
// thrown away). But be careful with overflow---we can't count on the
// open paren to be there.
if from > 0 { from = from - 1}
- let ast = try!(self.build_from(from, |l,r| Alt(~l, ~r)));
+ let ast = try!(self.build_from(from, |l,r| Alt(box l, box r)));
self.push(ast);
Ok(())
}
#[macro_registrar]
#[doc(hidden)]
pub fn macro_registrar(register: |ast::Name, SyntaxExtension|) {
- let expander = ~BasicMacroExpander { expander: native, span: None };
+ let expander = box BasicMacroExpander { expander: native, span: None };
register(token::intern("regex"), NormalTT(expander, None))
}
/// first before trying to understand the code generator. The implementation
/// strategy is identical and vm.rs has comments and will be easier to follow.
fn native(cx: &mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree])
- -> ~MacResult {
+ -> Box<MacResult> {
let regex = match parse(cx, tts) {
Some(r) => r,
// error is logged in 'parse' with cx.span_err
link_staticlib(sess, &obj_filename, &out_filename);
}
session::CrateTypeExecutable => {
- link_natively(sess, false, &obj_filename, &out_filename);
+ link_natively(sess, trans, false, &obj_filename, &out_filename);
}
session::CrateTypeDylib => {
- link_natively(sess, true, &obj_filename, &out_filename);
+ link_natively(sess, trans, true, &obj_filename, &out_filename);
}
}
//
// This will invoke the system linker/cc to create the resulting file. This
// links to all upstream files as well.
-fn link_natively(sess: &Session, dylib: bool, obj_filename: &Path,
- out_filename: &Path) {
+fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
+ obj_filename: &Path, out_filename: &Path) {
let tmpdir = TempDir::new("rustc").expect("needs a temp dir");
// The invocations of cc share some flags across platforms
let cc_prog = get_cc_prog(sess);
let mut cc_args = sess.targ_cfg.target_strs.cc_args.clone();
- cc_args.push_all_move(link_args(sess, dylib, tmpdir.path(),
+ cc_args.push_all_move(link_args(sess, dylib, tmpdir.path(), trans,
obj_filename, out_filename));
if (sess.opts.debugging_opts & session::PRINT_LINK_ARGS) != 0 {
println!("{} link args: '{}'", cc_prog, cc_args.connect("' '"));
fn link_args(sess: &Session,
dylib: bool,
tmpdir: &Path,
+ trans: &CrateTranslation,
obj_filename: &Path,
out_filename: &Path) -> Vec<~str> {
// this kind of behavior is pretty platform specific and generally not
// recommended anyway, so I don't think we're shooting ourself in the foot
// much with that.
- add_upstream_rust_crates(&mut args, sess, dylib, tmpdir);
+ add_upstream_rust_crates(&mut args, sess, dylib, tmpdir, trans);
add_local_native_libraries(&mut args, sess);
add_upstream_native_libraries(&mut args, sess);
// dependencies will be linked when producing the final output (instead of
// the intermediate rlib version)
fn add_upstream_rust_crates(args: &mut Vec<~str>, sess: &Session,
- dylib: bool, tmpdir: &Path) {
-
- // As a limitation of the current implementation, we require that everything
- // must be static or everything must be dynamic. The reasons for this are a
- // little subtle, but as with staticlibs and rlibs, the goal is to prevent
- // duplicate copies of the same library showing up. For example, a static
- // immediate dependency might show up as an upstream dynamic dependency and
- // we currently have no way of knowing that. We know that all dynamic
- // libraries require dynamic dependencies (see above), so it's satisfactory
- // to include either all static libraries or all dynamic libraries.
+ dylib: bool, tmpdir: &Path,
+ trans: &CrateTranslation) {
+ // All of the heavy lifting has previously been accomplished by the
+ // dependency_format module of the compiler. This is just crawling the
+ // output of that module, adding crates as necessary.
//
- // With this limitation, we expose a compiler default linkage type and an
- // option to reverse that preference. The current behavior looks like:
- //
- // * If a dylib is being created, upstream dependencies must be dylibs
- // * If nothing else is specified, static linking is preferred
- // * If the -C prefer-dynamic flag is given, dynamic linking is preferred
- // * If one form of linking fails, the second is also attempted
- // * If both forms fail, then we emit an error message
-
- let dynamic = get_deps(&sess.cstore, cstore::RequireDynamic);
- let statik = get_deps(&sess.cstore, cstore::RequireStatic);
- match (dynamic, statik, sess.opts.cg.prefer_dynamic, dylib) {
- (_, Some(deps), false, false) => {
- add_static_crates(args, sess, tmpdir, deps)
- }
-
- (None, Some(deps), true, false) => {
- // If you opted in to dynamic linking and we decided to emit a
- // static output, you should probably be notified of such an event!
- sess.warn("dynamic linking was preferred, but dependencies \
- could not all be found in a dylib format.");
- sess.warn("linking statically instead, using rlibs");
- add_static_crates(args, sess, tmpdir, deps)
- }
+ // Linking to a rlib involves just passing it to the linker (the linker
+ // will slurp up the object files inside), and linking to a dynamic library
+ // involves just passing the right -l flag.
- (Some(deps), _, _, _) => add_dynamic_crates(args, sess, deps),
+ let data = if dylib {
+ trans.crate_formats.get(&session::CrateTypeDylib)
+ } else {
+ trans.crate_formats.get(&session::CrateTypeExecutable)
+ };
- (None, _, _, true) => {
- sess.err("dylib output requested, but some depenencies could not \
- be found in the dylib format");
- let deps = sess.cstore.get_used_crates(cstore::RequireDynamic);
- for (cnum, path) in deps.move_iter() {
- if path.is_some() { continue }
- let name = sess.cstore.get_crate_data(cnum).name.clone();
- sess.note(format!("dylib not found: {}", name));
+ // Invoke get_used_crates to ensure that we get a topological sorting of
+ // crates.
+ let deps = sess.cstore.get_used_crates(cstore::RequireDynamic);
+
+ for &(cnum, _) in deps.iter() {
+ // We may not pass all crates through to the linker. Some crates may
+ // appear statically in an existing dylib, meaning we'll pick up all the
+ // symbols from the dylib.
+ let kind = match *data.get(cnum as uint - 1) {
+ Some(t) => t,
+ None => continue
+ };
+ let src = sess.cstore.get_used_crate_source(cnum).unwrap();
+ match kind {
+ cstore::RequireDynamic => {
+ add_dynamic_crate(args, sess, src.dylib.unwrap())
}
- }
-
- (None, None, pref, false) => {
- let (pref, name) = if pref {
- sess.err("dynamic linking is preferred, but dependencies were \
- not found in either dylib or rlib format");
- (cstore::RequireDynamic, "dylib")
- } else {
- sess.err("dependencies were not all found in either dylib or \
- rlib format");
- (cstore::RequireStatic, "rlib")
- };
- sess.note(format!("dependencies not found in the `{}` format",
- name));
- for (cnum, path) in sess.cstore.get_used_crates(pref).move_iter() {
- if path.is_some() { continue }
- let name = sess.cstore.get_crate_data(cnum).name.clone();
- sess.note(name);
+ cstore::RequireStatic => {
+ add_static_crate(args, sess, tmpdir, cnum, src.rlib.unwrap())
}
}
+
}
// Converts a library file-stem into a cc -l argument
}
}
- // Attempts to find all dependencies with a certain linkage preference,
- // returning `None` if not all libraries could be found with that
- // preference.
- fn get_deps(cstore: &cstore::CStore, preference: cstore::LinkagePreference)
- -> Option<Vec<(ast::CrateNum, Path)> >
- {
- let crates = cstore.get_used_crates(preference);
- if crates.iter().all(|&(_, ref p)| p.is_some()) {
- Some(crates.move_iter().map(|(a, b)| (a, b.unwrap())).collect())
- } else {
- None
- }
- }
-
// Adds the static "rlib" versions of all crates to the command line.
- fn add_static_crates(args: &mut Vec<~str>, sess: &Session, tmpdir: &Path,
- crates: Vec<(ast::CrateNum, Path)>) {
- for (cnum, cratepath) in crates.move_iter() {
- // When performing LTO on an executable output, all of the
- // bytecode from the upstream libraries has already been
- // included in our object file output. We need to modify all of
- // the upstream archives to remove their corresponding object
- // file to make sure we don't pull the same code in twice.
- //
- // We must continue to link to the upstream archives to be sure
- // to pull in native static dependencies. As the final caveat,
- // on linux it is apparently illegal to link to a blank archive,
- // so if an archive no longer has any object files in it after
- // we remove `lib.o`, then don't link against it at all.
- //
- // If we're not doing LTO, then our job is simply to just link
- // against the archive.
- if sess.lto() {
- let name = sess.cstore.get_crate_data(cnum).name.clone();
- time(sess.time_passes(), format!("altering {}.rlib", name),
- (), |()| {
- let dst = tmpdir.join(cratepath.filename().unwrap());
- match fs::copy(&cratepath, &dst) {
- Ok(..) => {}
- Err(e) => {
- sess.err(format!("failed to copy {} to {}: {}",
- cratepath.display(),
- dst.display(),
- e));
- sess.abort_if_errors();
- }
- }
- let dst_str = dst.as_str().unwrap().to_owned();
- let mut archive = Archive::open(sess, dst);
- archive.remove_file(format!("{}.o", name));
- let files = archive.files();
- if files.iter().any(|s| s.ends_with(".o")) {
- args.push(dst_str);
+ fn add_static_crate(args: &mut Vec<~str>, sess: &Session, tmpdir: &Path,
+ cnum: ast::CrateNum, cratepath: Path) {
+ // When performing LTO on an executable output, all of the
+ // bytecode from the upstream libraries has already been
+ // included in our object file output. We need to modify all of
+ // the upstream archives to remove their corresponding object
+ // file to make sure we don't pull the same code in twice.
+ //
+ // We must continue to link to the upstream archives to be sure
+ // to pull in native static dependencies. As the final caveat,
+ // on linux it is apparently illegal to link to a blank archive,
+ // so if an archive no longer has any object files in it after
+ // we remove `lib.o`, then don't link against it at all.
+ //
+ // If we're not doing LTO, then our job is simply to just link
+ // against the archive.
+ if sess.lto() {
+ let name = sess.cstore.get_crate_data(cnum).name.clone();
+ time(sess.time_passes(), format!("altering {}.rlib", name),
+ (), |()| {
+ let dst = tmpdir.join(cratepath.filename().unwrap());
+ match fs::copy(&cratepath, &dst) {
+ Ok(..) => {}
+ Err(e) => {
+ sess.err(format!("failed to copy {} to {}: {}",
+ cratepath.display(),
+ dst.display(),
+ e));
+ sess.abort_if_errors();
}
- });
- } else {
- args.push(cratepath.as_str().unwrap().to_owned());
- }
+ }
+ let dst_str = dst.as_str().unwrap().to_owned();
+ let mut archive = Archive::open(sess, dst);
+ archive.remove_file(format!("{}.o", name));
+ let files = archive.files();
+ if files.iter().any(|s| s.ends_with(".o")) {
+ args.push(dst_str);
+ }
+ });
+ } else {
+ args.push(cratepath.as_str().unwrap().to_owned());
}
}
// Same thing as above, but for dynamic crates instead of static crates.
- fn add_dynamic_crates(args: &mut Vec<~str>, sess: &Session,
- crates: Vec<(ast::CrateNum, Path)> ) {
+ fn add_dynamic_crate(args: &mut Vec<~str>, sess: &Session,
+ cratepath: Path) {
// If we're performing LTO, then it should have been previously required
// that all upstream rust dependencies were available in an rlib format.
assert!(!sess.lto());
- for (_, cratepath) in crates.move_iter() {
- // Just need to tell the linker about where the library lives and
- // what its name is
- let dir = cratepath.dirname_str().unwrap();
- if !dir.is_empty() { args.push("-L" + dir); }
- let libarg = unlib(&sess.targ_cfg, cratepath.filestem_str().unwrap());
- args.push("-l" + libarg);
- }
+ // Just need to tell the linker about where the library lives and
+ // what its name is
+ let dir = cratepath.dirname_str().unwrap();
+ if !dir.is_empty() { args.push("-L" + dir); }
+ let libarg = unlib(&sess.targ_cfg, cratepath.filestem_str().unwrap());
+ args.push("-l" + libarg);
}
}
use metadata::creader::Loader;
use metadata;
use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
+use middle::dependency_format;
use middle;
use util::common::time;
use util::ppaux;
ty_cx: ty_cx,
exported_items: exported_items,
public_items: public_items,
- reachable: reachable_map
+ reachable: reachable_map,
}
}
pub link: LinkMeta,
pub metadata: Vec<u8>,
pub reachable: Vec<~str>,
+ pub crate_formats: dependency_format::Dependencies,
}
/// Run the translation phase to LLVM, after which the AST and analysis can
pub fn phase_4_translate_to_llvm(krate: ast::Crate,
analysis: CrateAnalysis,
outputs: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
- // Option dance to work around the lack of stack once closures.
let time_passes = analysis.ty_cx.sess.time_passes();
- let mut analysis = Some(analysis);
- time(time_passes, "translation", krate, |krate|
- trans::base::trans_crate(krate, analysis.take_unwrap(), outputs))
+
+ time(time_passes, "resolving dependency formats", (), |_|
+ dependency_format::calculate(&analysis.ty_cx));
+
+ // Option dance to work around the lack of stack once closures.
+ time(time_passes, "translation", (krate, analysis), |(krate, analysis)|
+ trans::base::trans_crate(krate, analysis, outputs))
}
/// Run LLVM itself, producing a bitcode file, assembly file or object file
let mut rdr = MemReader::new(src);
let out = match ofile {
- None => box io::stdout() as ~Writer,
+ None => box io::stdout() as Box<Writer>,
Some(p) => {
let r = io::File::create(&p);
match r {
- Ok(w) => box w as ~Writer,
+ Ok(w) => box w as Box<Writer>,
Err(e) => fail!("print-print failed to open {} due to {}",
p.display(), e),
}
pub struct Options {
// The crate config requested for the session, which may be combined
// with additional crate configurations during the compile process
- pub crate_types: Vec<CrateType> ,
+ pub crate_types: Vec<CrateType>,
pub gc: bool,
pub optimize: OptLevel,
EntryNone,
}
-#[deriving(Eq, Ord, Clone, TotalOrd, TotalEq)]
+#[deriving(Eq, Ord, Clone, TotalOrd, TotalEq, Hash)]
pub enum CrateType {
CrateTypeExecutable,
CrateTypeDylib,
pub mod cfg;
pub mod dead;
pub mod expr_use_visitor;
+ pub mod dependency_format;
}
pub mod front {
pub static tag_crate_triple: uint = 0x66;
+pub static tag_dylib_dependency_formats: uint = 0x67;
+
#[deriving(Clone, Show)]
pub struct LinkMeta {
pub crateid: CrateId,
let cdata = cstore.get_crate_data(def_id.krate);
decoder::get_tuple_struct_definition_if_ctor(&*cdata, def_id.node)
}
+
+pub fn get_dylib_dependency_formats(cstore: &cstore::CStore,
+ cnum: ast::CrateNum)
+ -> Vec<(ast::CrateNum, cstore::LinkagePreference)>
+{
+ let cdata = cstore.get_crate_data(cnum);
+ decoder::get_dylib_dependency_formats(&*cdata)
+}
pub span: Span,
}
-#[deriving(Eq)]
+#[deriving(Show, Eq, Clone)]
pub enum LinkagePreference {
RequireDynamic,
RequireStatic,
});
result
}
+
+pub fn get_dylib_dependency_formats(cdata: Cmd)
+ -> Vec<(ast::CrateNum, cstore::LinkagePreference)>
+{
+ let formats = reader::get_doc(reader::Doc(cdata.data()),
+ tag_dylib_dependency_formats);
+ let mut result = Vec::new();
+
+ debug!("found dylib deps: {}", formats.as_str_slice());
+ for spec in formats.as_str_slice().split(',') {
+ if spec.len() == 0 { continue }
+ let cnum = spec.split(':').nth(0).unwrap();
+ let link = spec.split(':').nth(1).unwrap();
+ let cnum = from_str(cnum).unwrap();
+ let cnum = match cdata.cnum_map.find(&cnum) {
+ Some(&n) => n,
+ None => fail!("didn't find a crate in the cnum_map")
+ };
+ result.push((cnum, if link == "d" {
+ cstore::RequireDynamic
+ } else {
+ cstore::RequireStatic
+ }));
+ }
+ return result;
+}
#![allow(non_camel_case_types)]
use back::svh::Svh;
+use driver::session;
use metadata::common::*;
use metadata::cstore;
use metadata::decoder;
ebml_w.end_tag();
}
+fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
+ ebml_w.start_tag(tag_dylib_dependency_formats);
+ match ecx.tcx.dependency_formats.borrow().find(&session::CrateTypeDylib) {
+ Some(arr) => {
+ let s = arr.iter().enumerate().filter_map(|(i, slot)| {
+ slot.map(|kind| format!("{}:{}", i + 1, match kind {
+ cstore::RequireDynamic => "d",
+ cstore::RequireStatic => "s",
+ }))
+ }).collect::<Vec<~str>>();
+ ebml_w.writer.write(s.connect(",").as_bytes());
+ }
+ None => {}
+ }
+ ebml_w.end_tag();
+}
+
// NB: Increment this as you change the metadata encoding version.
pub static metadata_encoding_version : &'static [u8] =
&[0x72, //'r' as u8,
encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid);
encode_crate_triple(&mut ebml_w, tcx.sess.targ_cfg.target_strs.target_triple);
encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
+ encode_dylib_dependency_formats(&mut ebml_w, &ecx);
let mut i = ebml_w.writer.tell().unwrap();
let crate_attrs = synthesize_crate_attrs(&ecx, krate);
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
- ty::ty_trait(~ty::TyTrait { def_id, ref substs, store, bounds }) => {
+ ty::ty_trait(box ty::TyTrait {
+ def_id,
+ ref substs,
+ store,
+ bounds
+ }) => {
mywrite!(w, "x[{}|", (cx.ds)(def_id));
enc_substs(w, cx, substs);
enc_trait_store(w, cx, store);
struct S { f: uint }
```
-and a variable `a: ~S`, then the rust expression `a.f` would correspond
+and a variable `a: Box<S>`, then the rust expression `a.f` would correspond
to an `LV` of `(*a).f`.
Here is the formal grammar for the types we'll consider:
```notrust
-TY = () | S<'LT...> | ~TY | & 'LT MQ TY | @ MQ TY
+TY = () | S<'LT...> | Box<TY> | & 'LT MQ TY | @ MQ TY
MQ = mut | imm | const
```
struct Foo { f: uint, g: uint }
...
'a: {
- let mut x: ~Foo = ...;
+ let mut x: Box<Foo> = ...;
let y = &mut (*x).f;
x = ...;
}
MUTABILITY(LV, MQ)
MUTABILITY(*LV, MQ) // M-Deref-Unique
- TYPE(LV) = ~Ty
+ TYPE(LV) = Box<Ty>
MUTABILITY(LV, MQ)
```
the pointer itself `LV` goes out of scope:
```notrust
- SCOPE(*LV) = SCOPE(LV) if LV has type ~T
+ SCOPE(*LV) = SCOPE(LV) if LV has type Box<T>
```
The scope of a managed referent is also the scope of the pointer. This
LIFETIME(LV, LT, MQ)
LIFETIME(*LV, LT, MQ) // L-Deref-Send
- TYPE(LV) = ~Ty
+ TYPE(LV) = Box<Ty>
LIFETIME(LV, LT, MQ)
```
```notrust
RESTRICTIONS(*LV, LT, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Send-Pointer
- TYPE(LV) = ~Ty
+ TYPE(LV) = Box<Ty>
RESTRICTIONS(LV, LT, ACTIONS|MUTATE|CLAIM) = RS
```
Let's look at a simple example:
```
-fn foo(a: ~int) {
- let b: ~int; // Gen bit 0.
+fn foo(a: Box<int>) {
+ let b: Box<int>; // Gen bit 0.
if cond { // Bits: 0
use(&*a);
fn move_suggestion(tcx: &ty::ctxt, ty: ty::t, default_msg: &'static str)
-> &'static str {
match ty::get(ty).sty {
- ty::ty_closure(~ty::ClosureTy { store: ty::RegionTraitStore(..), .. }) =>
+ ty::ty_closure(box ty::ClosureTy {
+ store: ty::RegionTraitStore(..),
+ ..
+ }) =>
"a non-copyable stack closure (capture it in a new closure, \
e.g. `|x| f(x)`, to override)",
_ if ty::type_moves_by_default(tcx, ty) =>
});
}
- fn pretty_print_to(&self, wr: ~io::Writer,
+ fn pretty_print_to(&self, wr: Box<io::Writer>,
blk: &ast::Block) -> io::IoResult<()> {
let mut ps = pprust::rust_printer_annotated(wr, self);
try!(ps.cbox(pprust::indent_unit));
struct MarkSymbolVisitor<'a> {
worklist: Vec<ast::NodeId>,
tcx: &'a ty::ctxt,
- live_symbols: ~HashSet<ast::NodeId>,
+ live_symbols: Box<HashSet<ast::NodeId>>,
}
impl<'a> MarkSymbolVisitor<'a> {
exported_items: &privacy::ExportedItems,
reachable_symbols: &NodeSet,
krate: &ast::Crate)
- -> ~HashSet<ast::NodeId> {
+ -> Box<HashSet<ast::NodeId>> {
let worklist = create_and_seed_worklist(tcx, exported_items,
reachable_symbols, krate);
let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist);
struct DeadVisitor<'a> {
tcx: &'a ty::ctxt,
- live_symbols: ~HashSet<ast::NodeId>,
+ live_symbols: Box<HashSet<ast::NodeId>>,
}
impl<'a> DeadVisitor<'a> {
--- /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.
+
+//! Resolution of mixing rlibs and dylibs
+//!
+//! When producing a final artifact, such as a dynamic library, the compiler has
+//! a choice between linking an rlib or linking a dylib of all upstream
+//! dependencies. The linking phase must guarantee, however, that a library only
+//! show up once in the object file. For example, it is illegal for library A to
+//! be statically linked to B and C in separate dylibs, and then link B and C
+//! into a crate D (because library A appears twice).
+//!
+//! The job of this module is to calculate what format each upstream crate
+//! should be used when linking each output type requested in this session. This
+//! generally follows this set of rules:
+//!
+//! 1. Each library must appear exactly once in the output.
+//! 2. Each rlib contains only one library (it's just an object file)
+//! 3. Each dylib can contain more than one library (due to static linking),
+//! and can also bring in many dynamic dependencies.
+//!
+//! With these constraints in mind, it's generally a very difficult problem to
+//! find a solution that's not "all rlibs" or "all dylibs". I have suspicions
+//! that NP-ness may come into the picture here...
+//!
+//! The current selection algorithm below looks mostly similar to:
+//!
+//! 1. If static linking is required, then require all upstream dependencies
+//! to be available as rlibs. If not, generate an error.
+//! 2. If static linking is requested (generating an executable), then
+//! attempt to use all upstream dependencies as rlibs. If any are not
+//! found, bail out and continue to step 3.
+//! 3. Static linking has failed, at least one library must be dynamically
+//! linked. Apply a heuristic by greedily maximizing the number of
+//! dynamically linked libraries.
+//! 4. Each upstream dependency available as a dynamic library is
+//! registered. The dependencies all propagate, adding to a map. It is
+//! possible for a dylib to add a static library as a dependency, but it
+//! is illegal for two dylibs to add the same static library as a
+//! dependency. The same dylib can be added twice. Additionally, it is
+//! illegal to add a static dependency when it was previously found as a
+//! dylib (and vice versa)
+//! 5. After all dynamic dependencies have been traversed, re-traverse the
+//! remaining dependencies and add them statically (if they haven't been
+//! added already).
+//!
+//! While not perfect, this algorithm should help support use-cases such as leaf
+//! dependencies being static while the larger tree of inner dependencies are
+//! all dynamic. This isn't currently very well battle tested, so it will likely
+//! fall short in some use cases.
+//!
+//! Currently, there is no way to specify the preference of linkage with a
+//! particular library (other than a global dynamic/static switch).
+//! Additionally, the algorithm is geared towards finding *any* solution rather
+//! than finding a number of solutions (there are normally quite a few).
+
+use collections::HashMap;
+use syntax::ast;
+
+use driver::session;
+use metadata::cstore;
+use metadata::csearch;
+use middle::ty;
+
+/// A list of dependencies for a certain crate type.
+///
+/// The length of this vector is the same as the number of external crates used.
+/// The value is None if the crate does not need to be linked (it was found
+/// statically in another dylib), or Some(kind) if it needs to be linked as
+/// `kind` (either static or dynamic).
+pub type DependencyList = Vec<Option<cstore::LinkagePreference>>;
+
+/// A mapping of all required dependencies for a particular flavor of output.
+///
+/// This is local to the tcx, and is generally relevant to one session.
+pub type Dependencies = HashMap<session::CrateType, DependencyList>;
+
+pub fn calculate(tcx: &ty::ctxt) {
+ let mut fmts = tcx.dependency_formats.borrow_mut();
+ for &ty in tcx.sess.crate_types.borrow().iter() {
+ fmts.insert(ty, calculate_type(&tcx.sess, ty));
+ }
+ tcx.sess.abort_if_errors();
+}
+
+fn calculate_type(sess: &session::Session,
+ ty: session::CrateType) -> DependencyList {
+ match ty {
+ // If the global prefer_dynamic switch is turned off, first attempt
+ // static linkage (this can fail).
+ session::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => {
+ match attempt_static(sess) {
+ Some(v) => return v,
+ None => {}
+ }
+ }
+
+ // No linkage happens with rlibs, we just needed the metadata (which we
+ // got long ago), so don't bother with anything.
+ session::CrateTypeRlib => return Vec::new(),
+
+ // Staticlibs must have all static dependencies. If any fail to be
+ // found, we generate some nice pretty errors.
+ session::CrateTypeStaticlib => {
+ match attempt_static(sess) {
+ Some(v) => return v,
+ None => {}
+ }
+ sess.cstore.iter_crate_data(|cnum, data| {
+ let src = sess.cstore.get_used_crate_source(cnum).unwrap();
+ if src.rlib.is_some() { return }
+ sess.err(format!("dependency `{}` not found in rlib format",
+ data.name));
+ });
+ return Vec::new();
+ }
+
+ // Everything else falls through below
+ session::CrateTypeExecutable | session::CrateTypeDylib => {},
+ }
+
+ let mut formats = HashMap::new();
+
+ // Sweep all crates for found dylibs. Add all dylibs, as well as their
+ // dependencies, ensuring there are no conflicts. The only valid case for a
+ // dependency to be relied upon twice is for both cases to rely on a dylib.
+ sess.cstore.iter_crate_data(|cnum, data| {
+ let src = sess.cstore.get_used_crate_source(cnum).unwrap();
+ if src.dylib.is_some() {
+ add_library(sess, cnum, cstore::RequireDynamic, &mut formats);
+ debug!("adding dylib: {}", data.name);
+ let deps = csearch::get_dylib_dependency_formats(&sess.cstore, cnum);
+ for &(depnum, style) in deps.iter() {
+ add_library(sess, depnum, style, &mut formats);
+ debug!("adding {}: {}", style,
+ sess.cstore.get_crate_data(depnum).name.clone());
+ }
+ }
+ });
+
+ // Collect what we've got so far in the return vector.
+ let mut ret = range(1, sess.cstore.next_crate_num()).map(|i| {
+ match formats.find(&i).map(|v| *v) {
+ v @ Some(cstore::RequireDynamic) => v,
+ _ => None,
+ }
+ }).collect::<Vec<_>>();
+
+ // Run through the dependency list again, and add any missing libraries as
+ // static libraries.
+ sess.cstore.iter_crate_data(|cnum, data| {
+ let src = sess.cstore.get_used_crate_source(cnum).unwrap();
+ if src.dylib.is_none() && !formats.contains_key(&cnum) {
+ assert!(src.rlib.is_some());
+ add_library(sess, cnum, cstore::RequireStatic, &mut formats);
+ *ret.get_mut(cnum as uint - 1) = Some(cstore::RequireStatic);
+ debug!("adding staticlib: {}", data.name);
+ }
+ });
+
+ // When dylib B links to dylib A, then when using B we must also link to A.
+ // It could be the case, however, that the rlib for A is present (hence we
+ // found metadata), but the dylib for A has since been removed.
+ //
+ // For situations like this, we perform one last pass over the dependencies,
+ // making sure that everything is available in the requested format.
+ for (cnum, kind) in ret.iter().enumerate() {
+ let cnum = cnum as ast::CrateNum;
+ let src = sess.cstore.get_used_crate_source(cnum + 1).unwrap();
+ match *kind {
+ None => continue,
+ Some(cstore::RequireStatic) if src.rlib.is_some() => continue,
+ Some(cstore::RequireDynamic) if src.dylib.is_some() => continue,
+ Some(kind) => {
+ let data = sess.cstore.get_crate_data(cnum + 1);
+ sess.err(format!("crate `{}` required to be available in {}, \
+ but it was not available in this form",
+ data.name,
+ match kind {
+ cstore::RequireStatic => "rlib",
+ cstore::RequireDynamic => "dylib",
+ }));
+ }
+ }
+ }
+
+ return ret;
+}
+
+fn add_library(sess: &session::Session,
+ cnum: ast::CrateNum,
+ link: cstore::LinkagePreference,
+ m: &mut HashMap<ast::CrateNum, cstore::LinkagePreference>) {
+ match m.find(&cnum) {
+ Some(&link2) => {
+ // If the linkages differ, then we'd have two copies of the library
+ // if we continued linking. If the linkages are both static, then we
+ // would also have two copies of the library (static from two
+ // different locations).
+ //
+ // This error is probably a little obscure, but I imagine that it
+ // can be refined over time.
+ if link2 != link || link == cstore::RequireStatic {
+ let data = sess.cstore.get_crate_data(cnum);
+ sess.err(format!("cannot satisfy dependencies so `{}` only \
+ shows up once", data.name));
+ sess.note("having upstream crates all available in one format \
+ will likely make this go away");
+ }
+ }
+ None => { m.insert(cnum, link); }
+ }
+}
+
+fn attempt_static(sess: &session::Session) -> Option<DependencyList> {
+ let crates = sess.cstore.get_used_crates(cstore::RequireStatic);
+ if crates.iter().all(|&(_, ref p)| p.is_some()) {
+ Some(crates.move_iter().map(|_| Some(cstore::RequireStatic)).collect())
+ } else {
+ None
+ }
+}
let fty = ty::node_id_to_type(cx.tcx, id);
match ty::get(fty).sty {
- ty::ty_closure(~ty::ClosureTy {
+ ty::ty_closure(box ty::ClosureTy {
store: ty::UniqTraitStore, bounds, ..
}) => b(|cx, fv| check_for_uniq(cx, fv, bounds)),
- ty::ty_closure(~ty::ClosureTy {
+ ty::ty_closure(box ty::ClosureTy {
store: ty::RegionTraitStore(region, _), bounds, ..
}) => b(|cx, fv| check_for_block(cx, fv, bounds, region)),
fn check_trait_cast(cx: &mut Context, source_ty: ty::t, target_ty: ty::t, span: Span) {
check_cast_for_escaping_regions(cx, source_ty, target_ty, span);
match ty::get(target_ty).sty {
- ty::ty_trait(~ty::TyTrait { bounds, .. }) => {
+ ty::ty_trait(box ty::TyTrait { bounds, .. }) => {
check_trait_cast_bounds(cx, span, source_ty, bounds);
}
_ => {}
("owned_heap_memory",
LintSpec {
lint: OwnedHeapMemory,
- desc: "use of owned (~ type) heap memory",
+ desc: "use of owned (Box type) heap memory",
default: allow
}),
("heap_memory",
LintSpec {
lint: HeapMemory,
- desc: "use of any (~ type or @ type) heap memory",
+ desc: "use of any (Box type or @ type) heap memory",
default: allow
}),
n_box += 1;
}
ty::ty_uniq(_) |
- ty::ty_trait(~ty::TyTrait { store: ty::UniqTraitStore, .. }) |
- ty::ty_closure(~ty::ClosureTy { store: ty::UniqTraitStore, .. }) => {
+ ty::ty_trait(box ty::TyTrait {
+ store: ty::UniqTraitStore, ..
+ }) |
+ ty::ty_closure(box ty::ClosureTy {
+ store: ty::UniqTraitStore,
+ ..
+ }) => {
n_uniq += 1;
}
if n_uniq > 0 && lint != ManagedHeapMemory {
let s = ty_to_str(cx.tcx, ty);
- let m = format!("type uses owned (~ type) pointers: {}", s);
+ let m = format!("type uses owned (Box type) pointers: {}", s);
cx.span_lint(lint, span, m);
}
pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
match ty::get(t).sty {
ty::ty_uniq(_) |
- ty::ty_trait(~ty::TyTrait { store: ty::UniqTraitStore, .. }) |
- ty::ty_closure(~ty::ClosureTy {store: ty::UniqTraitStore, ..}) => {
+ ty::ty_trait(box ty::TyTrait { store: ty::UniqTraitStore, .. }) |
+ ty::ty_closure(box ty::ClosureTy {store: ty::UniqTraitStore, ..}) => {
Some(deref_ptr(OwnedPtr))
}
let kind = ty::BorrowKind::from_mutbl(mt.mutbl);
Some(deref_ptr(BorrowedPtr(kind, r)))
}
- ty::ty_trait(~ty::TyTrait { store: ty::RegionTraitStore(r, mutbl), .. }) => {
+ ty::ty_trait(box ty::TyTrait {
+ store: ty::RegionTraitStore(r, mutbl),
+ ..
+ }) => {
let kind = ty::BorrowKind::from_mutbl(mutbl);
Some(deref_ptr(BorrowedPtr(kind, r)))
}
- ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(r, _), ..}) => {
+ ty::ty_closure(box ty::ClosureTy {
+ store: ty::RegionTraitStore(r, _),
+ ..
+ }) => {
Some(deref_ptr(BorrowedPtr(ty::ImmBorrow, r)))
}
* | VariantName(..., P&, ...)
* | [ ..., P&, ... ]
* | ( ..., P&, ... )
- * | ~P&
* | box P&
*/
* | [ ..., E&, ... ]
* | ( ..., E&, ... )
* | {...; E&}
- * | ~E&
+ * | box E&
* | E& as ...
* | ( E& )
*/
enum FailureHandler<'a> {
Infallible,
JumpToBasicBlock(BasicBlockRef),
- DynamicFailureHandlerClass(~DynamicFailureHandler<'a>),
+ DynamicFailureHandlerClass(Box<DynamicFailureHandler<'a>>),
}
impl<'a> FailureHandler<'a> {
if hint.is_ffi_safe() {
return true;
}
- // Option<~T> and similar are used in FFI. Rather than try to resolve type parameters
- // and recognize this case exactly, this overapproximates -- assuming that if a
- // non-C-like enum is being used in FFI then the user knows what they're doing.
+ // Option<Box<T>> and similar are used in FFI. Rather than try to
+ // resolve type parameters and recognize this case exactly, this
+ // overapproximates -- assuming that if a non-C-like enum is being
+ // used in FFI then the user knows what they're doing.
if variants.iter().any(|vi| !vi.args.is_empty()) {
return true;
}
reachable.push("rust_eh_personality_catch".to_owned()); // referenced from rt/rust_try.ll
let metadata_module = ccx.metadata_llmod;
+ let formats = ccx.tcx.dependency_formats.borrow().clone();
(ccx.tcx, CrateTranslation {
context: llcx,
metadata_module: metadata_module,
metadata: metadata,
reachable: reachable,
+ crate_formats: formats,
})
}
use syntax::ast;
use util::ppaux::Repr;
+
pub struct CleanupScope<'a> {
// The id of this cleanup scope. If the id is None,
// this is a *temporary scope* that is pushed during trans to
kind: CleanupScopeKind<'a>,
// Cleanups to run upon scope exit.
- cleanups: Vec<~Cleanup>,
+ cleanups: Vec<Box<Cleanup>>,
cached_early_exits: Vec<CachedEarlyExit>,
cached_landing_pad: Option<BasicBlockRef>,
self.ccx.tn.val_to_str(val),
ty.repr(self.ccx.tcx()));
- self.schedule_clean(cleanup_scope, drop as ~Cleanup);
+ self.schedule_clean(cleanup_scope, drop as Box<Cleanup>);
}
fn schedule_drop_immediate(&self,
self.ccx.tn.val_to_str(val),
ty.repr(self.ccx.tcx()));
- self.schedule_clean(cleanup_scope, drop as ~Cleanup);
+ self.schedule_clean(cleanup_scope, drop as Box<Cleanup>);
}
fn schedule_free_value(&self,
self.ccx.tn.val_to_str(val),
heap);
- self.schedule_clean(cleanup_scope, drop as ~Cleanup);
+ self.schedule_clean(cleanup_scope, drop as Box<Cleanup>);
}
fn schedule_clean(&self,
cleanup_scope: ScopeId,
- cleanup: ~Cleanup) {
+ cleanup: Box<Cleanup>) {
match cleanup_scope {
AstScope(id) => self.schedule_clean_in_ast_scope(id, cleanup),
CustomScope(id) => self.schedule_clean_in_custom_scope(id, cleanup),
fn schedule_clean_in_ast_scope(&self,
cleanup_scope: ast::NodeId,
- cleanup: ~Cleanup) {
+ cleanup: Box<Cleanup>) {
/*!
* Schedules a cleanup to occur upon exit from `cleanup_scope`.
* If `cleanup_scope` is not provided, then the cleanup is scheduled
fn schedule_clean_in_custom_scope(&self,
custom_scope: CustomScopeIndex,
- cleanup: ~Cleanup) {
+ cleanup: Box<Cleanup>) {
/*!
* Schedules a cleanup to occur in the top-most scope,
* which must be a temporary scope.
heap: Heap);
fn schedule_clean(&self,
cleanup_scope: ScopeId,
- cleanup: ~Cleanup);
+ cleanup: Box<Cleanup>);
fn schedule_clean_in_ast_scope(&self,
cleanup_scope: ast::NodeId,
- cleanup: ~Cleanup);
+ cleanup: Box<Cleanup>);
fn schedule_clean_in_custom_scope(&self,
custom_scope: CustomScopeIndex,
- cleanup: ~Cleanup);
+ cleanup: Box<Cleanup>);
fn needs_invoke(&self) -> bool;
fn get_landing_pad(&'a self) -> BasicBlockRef;
}
```
struct List {
value: int,
- tail: Option<~List>,
+ tail: Option<Box<List>>,
}
```
```
describe(t = List)
describe(t = int)
- describe(t = Option<~List>)
- describe(t = ~List)
+ describe(t = Option<Box<List>>)
+ describe(t = Box<List>)
describe(t = List) // at the beginning again...
...
```
}
enum FunctionDebugContextRepr {
- FunctionDebugContext(~FunctionDebugContextData),
+ FunctionDebugContext(Box<FunctionDebugContextData>),
DebugInfoDisabled,
FunctionWithoutDebugInfo,
}
impl FunctionDebugContext {
fn get_ref<'a>(&'a self, cx: &CrateContext, span: Span) -> &'a FunctionDebugContextData {
match self.repr {
- FunctionDebugContext(~ref data) => data,
+ FunctionDebugContext(box ref data) => data,
DebugInfoDisabled => {
cx.sess().span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
}
set_debug_location(fcx.ccx, UnknownLocation);
return;
}
- FunctionDebugContext(~ref function_debug_context) => {
+ FunctionDebugContext(box ref function_debug_context) => {
let cx = fcx.ccx;
debug!("set_source_location: {}", cx.sess().codemap().span_to_str(span));
/// translated.
pub fn start_emitting_source_locations(fcx: &FunctionContext) {
match fcx.debug_context.repr {
- FunctionDebugContext(~ref data) => {
+ FunctionDebugContext(box ref data) => {
data.source_locations_enabled.set(true)
},
_ => { /* safe to ignore */ }
ty::ty_closure(ref closurety) => {
subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
}
- ty::ty_trait(~ty::TyTrait { def_id, ref substs, store, ref bounds }) => {
+ ty::ty_trait(box ty::TyTrait {
+ def_id,
+ ref substs,
+ store,
+ ref bounds
+ }) => {
trait_metadata(cx, def_id, t, substs, store, bounds)
}
ty::ty_struct(def_id, ref substs) => {
up expressions into:
- **Datum expressions:** Those that most naturally yield values.
- Examples would be `22`, `~x`, or `a + b` (when not overloaded).
+ Examples would be `22`, `box x`, or `a + b` (when not overloaded).
- **DPS expressions:** Those that most naturally write into a location
in memory. Examples would be `foo()` or `Point { x: 3, y: 4 }`.
- **Statement expressions:** That that do not generate a meaningful
when trans'd. Ultimately the reason for this is to micro-optimize
the resulting LLVM. For example, consider the following code:
- fn foo() -> ~int { ... }
+ fn foo() -> Box<int> { ... }
let x = *foo();
The expression `*foo()` is an lvalue, but if you invoke `expr::trans`,
drop uninitialized memory. If the initialization itself produces
byproducts that need to be freed, then you should use temporary custom
scopes to ensure that those byproducts will get freed on unwind. For
-example, an expression like `~foo()` will first allocate a box in the
+example, an expression like `box foo()` will first allocate a box in the
heap and then call `foo()` -- if `foo()` should fail, this box needs
to be *shallowly* freed.
which time the complete value should be stored in an lvalue or some
other place where normal cleanup applies.
-To spell it out, here is an example. Imagine an expression `~expr`.
+To spell it out, here is an example. Imagine an expression `box expr`.
We would basically:
1. Push a custom cleanup scope C.
-2. Allocate the `~` box.
+2. Allocate the box.
3. Schedule a shallow free in the scope C.
4. Trans `expr` into the box.
5. Pop the scope C.
DatumBlock(bcx, datum)
}
ast::ExprBox(_, contents) => {
- // Special case for `~T`. (The other case, for GC, is handled in
- // `trans_rvalue_dps_unadjusted`.)
+ // Special case for `box T`. (The other case, for GC, is handled
+ // in `trans_rvalue_dps_unadjusted`.)
let box_ty = expr_ty(bcx, expr);
let contents_ty = expr_ty(bcx, contents);
trans_uniq_expr(bcx, box_ty, contents, contents_ty)
let llty = type_of::type_of(bcx.ccx(), contents_ty);
let size = llsize_of(bcx.ccx(), llty);
// We need to a make a pointer type because box_ty is ty_bot
- // if content_ty is, e.g. ~fail!().
+ // if content_ty is, e.g. box fail!().
let real_box_ty = ty::mk_uniq(bcx.tcx(), contents_ty);
let Result { bcx, val } = malloc_raw_dyn(bcx, real_box_ty, size);
- // Unique boxes do not allocate for zero-size types. The standard library may assume
- // that `free` is never called on the pointer returned for `~ZeroSizeType`.
+ // Unique boxes do not allocate for zero-size types. The standard library
+ // may assume that `free` is never called on the pointer returned for
+ // `Box<ZeroSizeType>`.
let bcx = if llsize_of_alloc(bcx.ccx(), llty) == 0 {
trans_into(bcx, contents, SaveIn(val))
} else {
* Basically, the idea is to make the deref of an rvalue
* result in an rvalue. This helps to avoid intermediate stack
* slots in the resulting LLVM. The idea here is that, if the
- * `~T` pointer is an rvalue, then we can schedule a *shallow*
- * free of the `~T` pointer, and then return a ByRef rvalue
+ * `Box<T>` pointer is an rvalue, then we can schedule a *shallow*
+ * free of the `Box<T>` pointer, and then return a ByRef rvalue
* into the pointer. Because the free is shallow, it is legit
* to return an rvalue, because we know that the contents are
* not yet scheduled to be freed. The language rules ensure that the
let llty = sizing_type_of(ccx, typ);
// Unique boxes do not allocate for zero-size types. The standard
// library may assume that `free` is never called on the pointer
- // returned for `~ZeroSizeType`.
+ // returned for `Box<ZeroSizeType>`.
if llsize_of_alloc(ccx, llty) == 0 {
ty::mk_i8()
} else {
}
}
}
- ty::ty_trait(~ty::TyTrait { store: ty::UniqTraitStore, .. }) => {
+ ty::ty_trait(box ty::TyTrait { store: ty::UniqTraitStore, .. }) => {
let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
// Only drop the value when it is non-null
with_cond(bcx, IsNotNull(bcx, Load(bcx, lluniquevalue)), |bcx| {
-> Callee<'a> {
/*!
* Create a method callee where the method is coming from a trait
- * object (e.g., ~Trait type). In this case, we must pull the fn
+ * object (e.g., Box<Trait> type). In this case, we must pull the fn
* pointer out of the vtable that is packaged up with the object.
* Objects are represented as a pair, so we first evaluate the self
* expression and then extract the self data and vtable out of the
// Load the function from the vtable and cast it to the expected type.
debug!("(translating trait callee) loading method");
- // Replace the self type (&Self or ~Self) with an opaque pointer.
+ // Replace the self type (&Self or Box<Self>) with an opaque pointer.
let llcallee_ty = match ty::get(callee_ty).sty {
ty::ty_bare_fn(ref f) if f.abi == Rust => {
type_of_rust_fn(ccx, true, f.sig.inputs.slice_from(1), f.sig.output)
dest: expr::Dest)
-> &'a Block<'a> {
/*!
- * Generates the code to convert from a pointer (`~T`, `&T`, etc)
- * into an object (`~Trait`, `&Trait`, etc). This means creating a
+ * Generates the code to convert from a pointer (`Box<T>`, `&T`, etc)
+ * into an object (`Box<Trait>`, `&Trait`, etc). This means creating a
* pair where the first word is the vtable and the second word is
* the pointer.
*/
use metadata::csearch;
use mc = middle::mem_categorization;
use middle::const_eval;
+use middle::dependency_format;
use middle::lang_items::{ExchangeHeapLangItem, OpaqueStructLangItem};
use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem};
use middle::freevars;
#[deriving(Clone, Eq, TotalEq, Hash, Encodable, Decodable, Show)]
pub enum TraitStore {
- /// ~Trait
+ /// Box<Trait>
UniqTraitStore,
/// &Trait and &mut Trait
RegionTraitStore(Region, ast::Mutability),
/// Convert from T to *T
AutoUnsafe(ast::Mutability),
- /// Convert from ~Trait/&Trait to &Trait
+ /// Convert from Box<Trait>/&Trait to &Trait
AutoBorrowObj(Region, ast::Mutability),
}
pub struct ctxt {
// Specifically use a speedy hash algorithm for this hash map, it's used
// quite often.
- pub interner: RefCell<FnvHashMap<intern_key, ~t_box_>>,
+ pub interner: RefCell<FnvHashMap<intern_key, Box<t_box_>>>,
pub next_id: Cell<uint>,
pub sess: Session,
pub def_map: resolve::DefMap,
pub method_map: typeck::MethodMap,
pub vtable_map: typeck::vtable_map,
+
+ pub dependency_formats: RefCell<dependency_format::Dependencies>,
}
pub enum tbox_flag {
ty_ptr(mt),
ty_rptr(Region, mt),
ty_bare_fn(BareFnTy),
- ty_closure(~ClosureTy),
- ty_trait(~TyTrait),
+ ty_closure(Box<ClosureTy>),
+ ty_trait(Box<TyTrait>),
ty_struct(DefId, substs),
ty_tup(Vec<t>),
extern_const_variants: RefCell::new(DefIdMap::new()),
method_map: RefCell::new(FnvHashMap::new()),
vtable_map: RefCell::new(FnvHashMap::new()),
+ dependency_formats: RefCell::new(HashMap::new()),
}
}
&ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
flags |= sflags(substs);
}
- &ty_trait(~ty::TyTrait { ref substs, store, .. }) => {
+ &ty_trait(box ty::TyTrait { ref substs, store, .. }) => {
flags |= sflags(substs);
match store {
RegionTraitStore(r, _) => {
maybe_walk_ty(tm.ty, f);
}
ty_enum(_, ref substs) | ty_struct(_, ref substs) |
- ty_trait(~TyTrait { ref substs, .. }) => {
+ ty_trait(box TyTrait { ref substs, .. }) => {
for subty in (*substs).tps.iter() { maybe_walk_ty(*subty, |x| f(x)); }
}
ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
pub fn owned_pointer(&self) -> TypeContents {
/*!
* Includes only those bits that still apply
- * when indirected through a `~` pointer
+ * when indirected through a `Box` pointer
*/
TC::OwnsOwned | (
*self & (TC::OwnsAll | TC::ReachesAll))
// private cache for this walk. This is needed in the case of cyclic
// types like:
//
- // struct List { next: ~Option<List>, ... }
+ // struct List { next: Box<Option<List>>, ... }
//
// When computing the type contents of such a type, we wind up deeply
// recursing as we go. So when we encounter the recursive reference
}
}
- ty_trait(~ty::TyTrait { store, bounds, .. }) => {
+ ty_trait(box ty::TyTrait { store, bounds, .. }) => {
object_contents(cx, store, bounds)
}
fn borrow_obj(cx: &ctxt, span: Span, r: Region,
m: ast::Mutability, ty: ty::t) -> ty::t {
match get(ty).sty {
- ty_trait(~ty::TyTrait {def_id, ref substs, bounds, .. }) => {
+ ty_trait(box ty::TyTrait {def_id, ref substs, bounds, .. }) => {
ty::mk_trait(cx, def_id, substs.clone(),
RegionTraitStore(r, m), bounds)
}
// writing) it's not easy to distinguish casts to traits
// from other casts based on the AST. This should be
// easier in the future, when casts to traits
- // would like @Foo, ~Foo, or &Foo.
+ // would like @Foo, Box<Foo>, or &Foo.
RvalueDatumExpr
}
}
}
ast::ExprBox(place, _) => {
- // Special case `~T` for now:
+ // Special case `Box<T>` for now:
let definition = match tcx.def_map.borrow().find(&place.id) {
Some(&def) => def,
None => fail!("no def for place"),
ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
ty_box(_) => "@-ptr".to_owned(),
- ty_uniq(_) => "~-ptr".to_owned(),
+ ty_uniq(_) => "box".to_owned(),
ty_vec(_, _) => "vector".to_owned(),
ty_ptr(_) => "*-ptr".to_owned(),
ty_rptr(_, _) => "&-ptr".to_owned(),
pub fn ty_to_def_id(ty: t) -> Option<ast::DefId> {
match get(ty).sty {
- ty_trait(~TyTrait { def_id: id, .. }) | ty_struct(id, _) | ty_enum(id, _) => Some(id),
+ ty_trait(box TyTrait { def_id: id, .. }) |
+ ty_struct(id, _) |
+ ty_enum(id, _) => Some(id),
_ => None
}
}
}
}
}
- ty_trait(~ty::TyTrait { def_id: d, store, bounds, .. }) => {
+ ty_trait(box ty::TyTrait { def_id: d, store, bounds, .. }) => {
byte!(17);
did(&mut state, d);
match store {
ty::ty_enum(tid, ref substs) => {
ty::ty_enum(tid, this.fold_substs(substs))
}
- ty::ty_trait(~ty::TyTrait { def_id, ref substs, store, bounds }) => {
- ty::ty_trait(box ty::TyTrait{
+ ty::ty_trait(box ty::TyTrait {
+ def_id,
+ ref substs,
+ store,
+ bounds
+ }) => {
+ ty::ty_trait(box ty::TyTrait {
def_id: def_id,
substs: this.fold_substs(substs),
store: this.fold_trait_store(store),
//! legal.
//! If no bounds were specified, we choose a "default" bound based on
//! the allocation type of the fn/trait, as per issue #7264. The user can
- //! override this with an empty bounds list, e.g. "~fn:()" or "~Trait:".
+ //! override this with an empty bounds list, e.g. "Box<fn:()>" or
+ //! "Box<Trait:>".
match (ast_bounds, store) {
(&Some(ref bound_vec), _) => {
}
}
-// Helper function to check @, ~ and & patterns
+// Helper function to check @, box and & patterns
pub fn check_pointer_pat(pcx: &pat_ctxt,
pointer_kind: PointerKind,
inner: &ast::Pat,
e, actual)})},
Some(expected),
format!("{} pattern", match pointer_kind {
- Send => "a `~`-box",
+ Send => "a box",
Borrowed => "an `&`-pointer"
}),
None);
module as the type itself).
Inherent candidates are not always derived from impls. If you have a
-trait instance, such as a value of type `~ToStr`, then the trait
+trait instance, such as a value of type `Box<ToStr>`, then the trait
methods (`to_str()`, in this case) are inherently associated with it.
Another case is type parameters, in which case the methods of their
bounds are inherent.
proceed by progressively deref'ing the receiver type, after all. The
answer is that two phases are needed to elegantly deal with explicit
self. After all, if there is an impl for the type `Foo`, it can
-define a method with the type `~self`, which means that it expects a
-receiver of type `~Foo`. If we have a receiver of type `~Foo`, but we
-waited to search for that impl until we have deref'd the `~` away and
+define a method with the type `Box<self>`, which means that it expects a
+receiver of type `Box<Foo>`. If we have a receiver of type `Box<Foo>`, but we
+waited to search for that impl until we have deref'd the `Box` away and
obtained the type `Foo`, we would never match this method.
*/
*
* trait Foo {
* fn r_method<'a>(&'a self);
- * fn u_method(~self);
+ * fn u_method(Box<self>);
* }
*
* Now, assuming that `r_method` is being called, we want the
* result to be `&'a Foo`. Assuming that `u_method` is being
- * called, we want the result to be `~Foo`. Of course,
+ * called, we want the result to be `Box<Foo>`. Of course,
* this transformation has already been done as part of
* `method_ty.fty.sig.inputs[0]`, but there the type
- * is expressed in terms of `Self` (i.e., `&'a Self`, `~Self`).
+ * is expressed in terms of `Self` (i.e., `&'a Self`, `Box<Self>`).
* Because objects are not standalone types, we can't just substitute
* `s/Self/Foo/`, so we must instead perform this kind of hokey
* match below.
/// considered to "match" a given method candidate. Typically the test
/// is whether the receiver is of a particular type. However, this
/// type is the type of the receiver *after accounting for the
-/// method's self type* (e.g., if the method is an `~self` method, we
-/// have *already verified* that the receiver is of some type `~T` and
+/// method's self type* (e.g., if the method is an `Box<self>` method, we
+/// have *already verified* that the receiver is of some type `Box<T>` and
/// now we must check that the type `T` is correct). Unfortunately,
/// because traits are not types, this is a pain to do.
#[deriving(Clone)]
* `self.inherent_candidates`. See comment at the start of
* the file. To find the inherent candidates, we repeatedly
* deref the self-ty to find the "base-type". So, for
- * example, if the receiver is ~~C where `C` is a struct type,
+ * example, if the receiver is Box<Box<C>> where `C` is a struct type,
* we'll want to find the inherent impls for `C`.
*/
let span = self.self_expr.map_or(self.span, |e| e.span);
check::autoderef(self.fcx, span, self_ty, None, PreferMutLvalue, |self_ty, _| {
match get(self_ty).sty {
- ty_trait(~TyTrait { def_id, ref substs, .. }) => {
+ ty_trait(box TyTrait { def_id, ref substs, .. }) => {
self.push_inherent_candidates_from_object(def_id, substs);
self.push_inherent_impl_candidates_for_type(def_id);
}
* consuming the original pointer.
*
* You might think that this would be a natural byproduct of
- * the auto-deref/auto-ref process. This is true for `~T`
- * but not for an `&mut T` receiver. With `~T`, we would
- * begin by testing for methods with a self type `~T`,
+ * the auto-deref/auto-ref process. This is true for `Box<T>`
+ * but not for an `&mut T` receiver. With `Box<T>`, we would
+ * begin by testing for methods with a self type `Box<T>`,
* then autoderef to `T`, then autoref to `&mut T`. But with
* an `&mut T` receiver the process begins with `&mut T`, only
* without any autoadjustments.
autoref: Some(auto)})
}
- ty::ty_trait(~ty::TyTrait {
+ ty::ty_trait(box ty::TyTrait {
def_id, ref substs, store: ty::RegionTraitStore(_, mutbl), bounds
}) => {
let region =
},
ty_vec(mt, Some(_)) => self.auto_slice_vec(mt, autoderefs),
- ty_trait(~ty::TyTrait { def_id: trt_did, substs: trt_substs, bounds: b, .. }) => {
- // Coerce ~/&Trait instances to &Trait.
+ ty_trait(box ty::TyTrait {
+ def_id: trt_did,
+ substs: trt_substs,
+ bounds: b,
+ ..
+ }) => {
+ // Coerce Box/&Trait instances to &Trait.
self.search_for_some_kind_of_autorefd_method(
AutoBorrowObj, autoderefs, [MutImmutable, MutMutable],
}
}
- ty::ty_trait(~ty::TyTrait {
+ ty::ty_trait(box ty::TyTrait {
def_id: self_did, store: RegionTraitStore(_, self_m), ..
}) => {
mutability_matches(self_m, m) &&
}
}
- ty::ty_trait(~ty::TyTrait {
+ ty::ty_trait(box ty::TyTrait {
def_id: self_did, store: UniqTraitStore, ..
}) => {
rcvr_matches_object(self_did, candidate)
let fn_sig = match *fn_sty {
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
- ty::ty_closure(~ty::ClosureTy {sig: ref sig, ..}) => sig,
+ ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
_ => {
fcx.type_error_message(call_expr.span, |actual| {
format!("expected function but \
// accessed. We must be wary of loops like this:
//
// // from src/test/compile-fail/borrowck-lend-flow.rs
- // let mut v = ~3, w = ~4;
+ // let mut v = box 3, w = box 4;
// let mut x = &mut w;
// loop {
// **x += 1; // (2)
// explaining how it goes about doing that.
let target_ty = rcx.resolve_node_type(expr.id);
match ty::get(target_ty).sty {
- ty::ty_trait(~ty::TyTrait {
+ ty::ty_trait(box ty::TyTrait {
store: ty::RegionTraitStore(trait_region, _), ..
}) => {
let source_ty = rcx.resolve_expr_type_adjusted(source);
let tcx = rcx.fcx.tcx();
let function_type = rcx.resolve_node_type(expr.id);
match ty::get(function_type).sty {
- ty::ty_closure(~ty::ClosureTy {
+ ty::ty_closure(box ty::ClosureTy {
store: ty::RegionTraitStore(region, _), ..}) => {
freevars::with_freevars(tcx, expr.id, |freevars| {
if freevars.is_empty() {
rcx.set_repeating_scope(repeating_scope);
match ty::get(function_type).sty {
- ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(..), ..}) => {
+ ty::ty_closure(box ty::ClosureTy {
+ store: ty::RegionTraitStore(..),
+ ..
+ }) => {
freevars::with_freevars(tcx, expr.id, |freevars| {
propagate_upupvar_borrow_kind(rcx, expr, freevars);
})
let resolve_object_cast = |src: &ast::Expr, target_ty: ty::t| {
match ty::get(target_ty).sty {
// Bounds of type's contents are not checked here, but in kind.rs.
- ty::ty_trait(~ty::TyTrait {
+ ty::ty_trait(box ty::TyTrait {
def_id: target_def_id, substs: ref target_substs, store, ..
}) => {
fn mutability_allowed(a_mutbl: ast::Mutability,
// Look up vtables for the type we're casting to,
// passing in the source and target type. The source
// must be a pointer type suitable to the object sigil,
- // e.g.: `&x as &Trait` or `~x as ~Trait`
+ // e.g.: `&x as &Trait` or `box x as Box<Trait>`
let ty = structurally_resolved_type(fcx, ex.span,
fcx.expr_ty(src));
match (&ty::get(ty).sty, store) {
(_, ty::UniqTraitStore) => {
fcx.ccx.tcx.sess.span_err(
ex.span,
- format!("can only cast an ~-pointer \
- to a ~-object, not a {}",
+ format!("can only cast an boxed pointer \
+ to a boxed object, not a {}",
ty::ty_sort_str(fcx.tcx(), ty)));
}
ty::walk_ty(original_type, |t| {
match get(t).sty {
ty_enum(def_id, _) |
- ty_trait(~ty::TyTrait { def_id, .. }) |
+ ty_trait(box ty::TyTrait { def_id, .. }) |
ty_struct(def_id, _) => {
if def_id.krate == ast::LOCAL_CRATE {
found_nominal = true;
match get(base_type).sty {
ty_enum(def_id, _) |
ty_struct(def_id, _) |
- ty_trait(~ty::TyTrait { def_id, .. }) => {
+ ty_trait(box ty::TyTrait { def_id, .. }) => {
return Some(def_id);
}
_ => {
};
}
- ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(..), ..}) => {
+ ty::ty_closure(box ty::ClosureTy {
+ store: ty::RegionTraitStore(..),
+ ..
+ }) => {
return self.unpack_actual_value(a, |sty_a| {
self.coerce_borrowed_fn(a, sty_a, b)
});
});
}
- ty::ty_trait(~ty::TyTrait {
+ ty::ty_trait(box ty::TyTrait {
def_id, ref substs, store: ty::UniqTraitStore, bounds
}) => {
let result = self.unpack_actual_value(a, |sty_a| {
}
}
- ty::ty_trait(~ty::TyTrait {
+ ty::ty_trait(box ty::TyTrait {
def_id, ref substs, store: ty::RegionTraitStore(region, m), bounds
}) => {
let result = self.unpack_actual_value(a, |sty_a| {
let r_a = self.get_ref().infcx.next_region_var(coercion);
let a_borrowed = match *sty_a {
- ty::ty_trait(~ty::TyTrait { def_id, ref substs, bounds, .. }) => {
+ ty::ty_trait(box ty::TyTrait {
+ def_id,
+ ref substs,
+ bounds,
+ ..
+ }) => {
ty::mk_trait(tcx, def_id, substs.clone(),
ty::RegionTraitStore(r_a, b_mutbl), bounds)
}
ty::EmptyBuiltinBounds());
let dummy1 = self.resolve_type_vars_if_possible(dummy0);
match ty::get(dummy1).sty {
- ty::ty_trait(~ty::TyTrait { ref def_id, ref substs, .. }) => {
+ ty::ty_trait(box ty::TyTrait { ref def_id, ref substs, .. }) => {
ty::TraitRef {
def_id: *def_id,
substs: (*substs).clone(),
*p += 1; *p
}
fn weird() {
- let mut x: ~Foo = ~Foo { ... };
+ let mut x: Box<Foo> = box Foo { ... };
'a: add(&mut (*x).f,
'b: inc(&mut (*x).f)) // (..)
}
*p += v;
}
...
- fn consume(x: ~Foo) -> uint {
+ fn consume(x: Box<Foo>) -> uint {
x.f + x.g
}
fn weird() {
- let mut x: ~Foo = ~Foo { ... };
+ let mut x: Box<Foo> = box Foo { ... };
'a: add(&mut (*x).f, consume(x)) // (..)
}
substs, variance);
}
- ty::ty_trait(~ty::TyTrait { def_id, ref substs, .. }) => {
+ ty::ty_trait(box ty::TyTrait { def_id, ref substs, .. }) => {
let trait_def = ty::lookup_trait_def(self.tcx(), def_id);
self.add_constraints_from_substs(def_id, &trait_def.generics,
substs, variance);
}
ty::ty_bare_fn(ty::BareFnTy { ref sig, .. }) |
- ty::ty_closure(~ty::ClosureTy { ref sig, store: ty::UniqTraitStore, .. }) => {
+ ty::ty_closure(box ty::ClosureTy {
+ ref sig,
+ store: ty::UniqTraitStore,
+ ..
+ }) => {
self.add_constraints_from_sig(sig, variance);
}
- ty::ty_closure(~ty::ClosureTy { ref sig,
+ ty::ty_closure(box ty::ClosureTy { ref sig,
store: ty::RegionTraitStore(region, _), .. }) => {
let contra = self.contravariant(variance);
self.add_constraints_from_region(region, contra);
pub fn trait_store_to_str(cx: &ctxt, s: ty::TraitStore) -> ~str {
match s {
- ty::UniqTraitStore => "~".to_owned(),
+ ty::UniqTraitStore => "Box ".to_owned(),
ty::RegionTraitStore(r, m) => {
format!("{}{}", region_ptr_to_str(cx, r), mutability_to_str(m))
}
did,
false)
}
- ty_trait(~ty::TyTrait {
+ ty_trait(box ty::TyTrait {
def_id: did, ref substs, store, ref bounds
}) => {
let base = ty::item_path_str(cx, did);
}
}
-impl<T:Repr> Repr for ~T {
+impl<T:Repr> Repr for Box<T> {
fn repr(&self, tcx: &ctxt) -> ~str {
(&**self).repr(tcx)
}
use syntax::parse::token::InternedString;
use syntax::parse::token;
+use rustc::back::link;
+use rustc::driver::driver;
use rustc::metadata::cstore;
use rustc::metadata::csearch;
use rustc::metadata::decoder;
impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> {
fn clean(&self) -> Crate {
- use syntax::attr::find_crateid;
let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
let mut externs = Vec::new();
externs.push((n, meta.clean()));
});
+ let input = driver::FileInput(cx.src.clone());
+ let t_outputs = driver::build_output_filenames(&input,
+ &None,
+ &None,
+ self.attrs.as_slice(),
+ cx.sess());
+ let id = link::find_crate_id(self.attrs.as_slice(),
+ t_outputs.out_filestem);
Crate {
- name: match find_crateid(self.attrs.as_slice()) {
- Some(n) => n.name,
- None => fail!("rustdoc requires a `crate_id` crate attribute"),
- },
+ name: id.name,
module: Some(self.module.clean()),
externs: externs,
}
Self(ast::NodeId),
/// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
Primitive(ast::PrimTy),
- Closure(~ClosureDecl, Option<Lifetime>),
- Proc(~ClosureDecl),
+ Closure(Box<ClosureDecl>, Option<Lifetime>),
+ Proc(Box<ClosureDecl>),
/// extern "ABI" fn
- BareFunction(~BareFunctionDecl),
+ BareFunction(Box<BareFunctionDecl>),
Tuple(Vec<Type>),
- Vector(~Type),
- FixedVector(~Type, ~str),
+ Vector(Box<Type>),
+ FixedVector(Box<Type>, ~str),
String,
Bool,
/// aka TyNil
Unit,
/// aka TyBot
Bottom,
- Unique(~Type),
- Managed(~Type),
- RawPointer(Mutability, ~Type),
+ Unique(Box<Type>),
+ Managed(Box<Type>),
+ RawPointer(Mutability, Box<Type>),
BorrowedRef {
pub lifetime: Option<Lifetime>,
pub mutability: Mutability,
- pub type_: ~Type,
+ pub type_: Box<Type>,
},
// region, raw, other boxes, mutable
}
impl Clean<Item> for doctree::Macro {
fn clean(&self) -> Item {
Item {
- name: Some(self.name.clean()),
+ name: Some(self.name.clean() + "!"),
attrs: self.attrs.clean(),
source: self.where.clean(),
visibility: ast::Public.clean(),
use rustc::{driver, middle};
use rustc::metadata::creader::Loader;
use rustc::middle::privacy;
+use rustc::middle::lint;
use syntax::ast;
use syntax::parse::token;
pub struct DocContext {
pub krate: ast::Crate,
- pub maybe_typed: MaybeTyped
+ pub maybe_typed: MaybeTyped,
+ pub src: Path,
}
impl DocContext {
maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
addl_lib_search_paths: RefCell::new(libs),
crate_types: vec!(driver::session::CrateTypeDylib),
+ lint_opts: vec!((lint::Warnings, lint::allow)),
..rustc::driver::session::basic_options().clone()
};
debug!("crate: {:?}", krate);
(DocContext {
krate: krate,
- maybe_typed: Typed(ty_cx)
+ maybe_typed: Typed(ty_cx),
+ src: cpath.clone(),
}, CrateAnalysis {
exported_items: exported_items,
public_items: public_items,
let klass = match next.tok {
// If this '&' token is directly adjacent to another token, assume
// that it's the address-of operator instead of the and-operator.
- // This allows us to give all pointers their own class (~ and @ are
- // below).
+ // This allows us to give all pointers their own class (`Box` and
+ // `@` are below).
t::BINOP(t::AND) if lexer.peek().sp.lo == next.sp.hi => "kw-2",
t::AT | t::TILDE => "kw-2",
//! Markdown formatting for rustdoc
//!
-//! This module implements markdown formatting through the sundown C-library
+//! This module implements markdown formatting through the hoedown C-library
//! (bundled into the rust runtime). This module self-contains the C bindings
//! and necessary legwork to render markdown, and exposes all of the
//! functionality through a unit-struct, `Markdown`, which has an implementation
#![allow(non_camel_case_types)]
use libc;
-use std::cast;
use std::fmt;
use std::io;
use std::local_data;
-use std::mem;
use std::str;
use std::slice;
use collections::HashMap;
/// table of contents.
pub struct MarkdownWithToc<'a>(pub &'a str);
-static OUTPUT_UNIT: libc::size_t = 64;
-static MKDEXT_NO_INTRA_EMPHASIS: libc::c_uint = 1 << 0;
-static MKDEXT_TABLES: libc::c_uint = 1 << 1;
-static MKDEXT_FENCED_CODE: libc::c_uint = 1 << 2;
-static MKDEXT_AUTOLINK: libc::c_uint = 1 << 3;
-static MKDEXT_STRIKETHROUGH: libc::c_uint = 1 << 4;
-
-type sd_markdown = libc::c_void; // this is opaque to us
-
-struct sd_callbacks {
- blockcode: Option<extern "C" fn(*buf, *buf, *buf, *libc::c_void)>,
- blockquote: Option<extern "C" fn(*buf, *buf, *libc::c_void)>,
- blockhtml: Option<extern "C" fn(*buf, *buf, *libc::c_void)>,
- header: Option<extern "C" fn(*buf, *buf, libc::c_int, *libc::c_void)>,
- other: [libc::size_t, ..22],
+static DEF_OUNIT: libc::size_t = 64;
+static HOEDOWN_EXT_NO_INTRA_EMPHASIS: libc::c_uint = 1 << 10;
+static HOEDOWN_EXT_TABLES: libc::c_uint = 1 << 0;
+static HOEDOWN_EXT_FENCED_CODE: libc::c_uint = 1 << 1;
+static HOEDOWN_EXT_AUTOLINK: libc::c_uint = 1 << 3;
+static HOEDOWN_EXT_STRIKETHROUGH: libc::c_uint = 1 << 4;
+static HOEDOWN_EXT_SUPERSCRIPT: libc::c_uint = 1 << 8;
+static HOEDOWN_EXT_FOOTNOTES: libc::c_uint = 1 << 2;
+
+static HOEDOWN_EXTENSIONS: libc::c_uint =
+ HOEDOWN_EXT_NO_INTRA_EMPHASIS | HOEDOWN_EXT_TABLES |
+ HOEDOWN_EXT_FENCED_CODE | HOEDOWN_EXT_AUTOLINK |
+ HOEDOWN_EXT_STRIKETHROUGH | HOEDOWN_EXT_SUPERSCRIPT |
+ HOEDOWN_EXT_FOOTNOTES;
+
+type hoedown_document = libc::c_void; // this is opaque to us
+
+struct hoedown_renderer {
+ opaque: *mut hoedown_html_renderer_state,
+ blockcode: Option<extern "C" fn(*mut hoedown_buffer, *hoedown_buffer,
+ *hoedown_buffer, *mut libc::c_void)>,
+ blockquote: Option<extern "C" fn(*mut hoedown_buffer, *hoedown_buffer,
+ *mut libc::c_void)>,
+ blockhtml: Option<extern "C" fn(*mut hoedown_buffer, *hoedown_buffer,
+ *mut libc::c_void)>,
+ header: Option<extern "C" fn(*mut hoedown_buffer, *hoedown_buffer,
+ libc::c_int, *mut libc::c_void)>,
+ other: [libc::size_t, ..28],
+}
+
+struct hoedown_html_renderer_state {
+ opaque: *mut libc::c_void,
+ toc_data: html_toc_data,
+ flags: libc::c_uint,
+ link_attributes: Option<extern "C" fn(*mut hoedown_buffer, *hoedown_buffer,
+ *mut libc::c_void)>,
}
struct html_toc_data {
header_count: libc::c_int,
current_level: libc::c_int,
level_offset: libc::c_int,
+ nesting_level: libc::c_int,
}
-struct html_renderopt {
- toc_data: html_toc_data,
- flags: libc::c_uint,
- link_attributes: Option<extern "C" fn(*buf, *buf, *libc::c_void)>,
-}
-
-struct my_opaque {
- opt: html_renderopt,
- dfltblk: extern "C" fn(*buf, *buf, *buf, *libc::c_void),
+struct MyOpaque {
+ dfltblk: extern "C" fn(*mut hoedown_buffer, *hoedown_buffer,
+ *hoedown_buffer, *mut libc::c_void),
toc_builder: Option<TocBuilder>,
}
-struct buf {
+struct hoedown_buffer {
data: *u8,
size: libc::size_t,
asize: libc::size_t,
unit: libc::size_t,
}
-// sundown FFI
-#[link(name = "sundown", kind = "static")]
+// hoedown FFI
+#[link(name = "hoedown", kind = "static")]
extern {
- fn sdhtml_renderer(callbacks: *sd_callbacks,
- options_ptr: *html_renderopt,
- render_flags: libc::c_uint);
- fn sd_markdown_new(extensions: libc::c_uint,
- max_nesting: libc::size_t,
- callbacks: *sd_callbacks,
- opaque: *libc::c_void) -> *sd_markdown;
- fn sd_markdown_render(ob: *buf,
- document: *u8,
- doc_size: libc::size_t,
- md: *sd_markdown);
- fn sd_markdown_free(md: *sd_markdown);
-
- fn bufnew(unit: libc::size_t) -> *buf;
- fn bufputs(b: *buf, c: *libc::c_char);
- fn bufrelease(b: *buf);
+ fn hoedown_html_renderer_new(render_flags: libc::c_uint,
+ nesting_level: libc::c_int)
+ -> *mut hoedown_renderer;
+ fn hoedown_html_renderer_free(renderer: *mut hoedown_renderer);
+
+ fn hoedown_document_new(rndr: *mut hoedown_renderer,
+ extensions: libc::c_uint,
+ max_nesting: libc::size_t) -> *mut hoedown_document;
+ fn hoedown_document_render(doc: *mut hoedown_document,
+ ob: *mut hoedown_buffer,
+ document: *u8,
+ doc_size: libc::size_t);
+ fn hoedown_document_free(md: *mut hoedown_document);
+
+ fn hoedown_buffer_new(unit: libc::size_t) -> *mut hoedown_buffer;
+ fn hoedown_buffer_puts(b: *mut hoedown_buffer, c: *libc::c_char);
+ fn hoedown_buffer_free(b: *mut hoedown_buffer);
}
local_data_key!(used_header_map: HashMap<~str, uint>)
pub fn render(w: &mut io::Writer, s: &str, print_toc: bool) -> fmt::Result {
- extern fn block(ob: *buf, text: *buf, lang: *buf, opaque: *libc::c_void) {
+ extern fn block(ob: *mut hoedown_buffer, text: *hoedown_buffer,
+ lang: *hoedown_buffer, opaque: *mut libc::c_void) {
unsafe {
- let my_opaque: &my_opaque = cast::transmute(opaque);
+ let opaque = opaque as *mut hoedown_html_renderer_state;
+ let my_opaque: &MyOpaque = &*((*opaque).opaque as *MyOpaque);
slice::raw::buf_as_slice((*text).data, (*text).size as uint, |text| {
let text = str::from_utf8(text).unwrap();
- let mut lines = text.lines().filter(|l| stripped_filtered_line(*l).is_none());
+ let mut lines = text.lines().filter(|l| {
+ stripped_filtered_line(*l).is_none()
+ });
let text = lines.collect::<Vec<&str>>().connect("\n");
- let buf = buf {
+ let buf = hoedown_buffer {
data: text.as_bytes().as_ptr(),
size: text.len() as libc::size_t,
asize: text.len() as libc::size_t,
(*lang).size as uint, |rlang| {
let rlang = str::from_utf8(rlang).unwrap();
if rlang.contains("notrust") {
- (my_opaque.dfltblk)(ob, &buf, lang, opaque);
+ (my_opaque.dfltblk)(ob, &buf, lang,
+ opaque as *mut libc::c_void);
true
} else {
false
if !rendered {
let output = highlight::highlight(text, None).to_c_str();
output.with_ref(|r| {
- bufputs(ob, r)
+ hoedown_buffer_puts(ob, r)
})
}
})
}
}
- extern fn header(ob: *buf, text: *buf, level: libc::c_int,
- opaque: *libc::c_void) {
- // sundown does this, we may as well too
- "\n".with_c_str(|p| unsafe { bufputs(ob, p) });
+ extern fn header(ob: *mut hoedown_buffer, text: *hoedown_buffer,
+ level: libc::c_int, opaque: *mut libc::c_void) {
+ // hoedown does this, we may as well too
+ "\n".with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) });
// Extract the text provided
let s = if text.is_null() {
}
}).collect::<Vec<~str>>().connect("-");
- let opaque = unsafe {&mut *(opaque as *mut my_opaque)};
+ // This is a terrible hack working around how hoedown gives us rendered
+ // html for text rather than the raw text.
+ let id = id.replace("<code>", "").replace("</code>", "");
+
+ let opaque = opaque as *mut hoedown_html_renderer_state;
+ let opaque = unsafe { &mut *((*opaque).opaque as *mut MyOpaque) };
// Make sure our hyphenated ID is unique for this page
let id = local_data::get_mut(used_header_map, |map| {
s, lvl = level, id = id,
sec_len = sec.len(), sec = sec);
- text.with_c_str(|p| unsafe { bufputs(ob, p) });
+ text.with_c_str(|p| unsafe { hoedown_buffer_puts(ob, p) });
}
- // This code is all lifted from examples/sundown.c in the sundown repo
unsafe {
- let ob = bufnew(OUTPUT_UNIT);
- let extensions = MKDEXT_NO_INTRA_EMPHASIS | MKDEXT_TABLES |
- MKDEXT_FENCED_CODE | MKDEXT_AUTOLINK |
- MKDEXT_STRIKETHROUGH;
- let options = html_renderopt {
- toc_data: html_toc_data {
- header_count: 0,
- current_level: 0,
- level_offset: 0,
- },
- flags: 0,
- link_attributes: None,
- };
- let mut callbacks: sd_callbacks = mem::init();
-
- sdhtml_renderer(&callbacks, &options, 0);
- let mut opaque = my_opaque {
- opt: options,
- dfltblk: callbacks.blockcode.unwrap(),
+ let ob = hoedown_buffer_new(DEF_OUNIT);
+ let renderer = hoedown_html_renderer_new(0, 0);
+ let mut opaque = MyOpaque {
+ dfltblk: (*renderer).blockcode.unwrap(),
toc_builder: if print_toc {Some(TocBuilder::new())} else {None}
};
- callbacks.blockcode = Some(block);
- callbacks.header = Some(header);
- let markdown = sd_markdown_new(extensions, 16, &callbacks,
- &mut opaque as *mut my_opaque as *libc::c_void);
+ (*(*renderer).opaque).opaque = &mut opaque as *mut _ as *mut libc::c_void;
+ (*renderer).blockcode = Some(block);
+ (*renderer).header = Some(header);
+ let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
+ hoedown_document_render(document, ob, s.as_ptr(),
+ s.len() as libc::size_t);
+ hoedown_document_free(document);
- sd_markdown_render(ob, s.as_ptr(), s.len() as libc::size_t, markdown);
- sd_markdown_free(markdown);
+ hoedown_html_renderer_free(renderer);
let mut ret = match opaque.toc_builder {
Some(b) => write!(w, "<nav id=\"TOC\">{}</nav>", b.into_toc()),
w.write(buf)
});
}
- bufrelease(ob);
+ hoedown_buffer_free(ob);
ret
}
}
pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) {
- extern fn block(_ob: *buf, text: *buf, lang: *buf, opaque: *libc::c_void) {
+ extern fn block(_ob: *mut hoedown_buffer, text: *hoedown_buffer,
+ lang: *hoedown_buffer, opaque: *mut libc::c_void) {
unsafe {
if text.is_null() { return }
let (should_fail, no_run, ignore, notrust) = if lang.is_null() {
};
if notrust { return }
slice::raw::buf_as_slice((*text).data, (*text).size as uint, |text| {
- let tests = &mut *(opaque as *mut ::test::Collector);
+ let opaque = opaque as *mut hoedown_html_renderer_state;
+ let tests = &mut *((*opaque).opaque as *mut ::test::Collector);
let text = str::from_utf8(text).unwrap();
- let mut lines = text.lines().map(|l| stripped_filtered_line(l).unwrap_or(l));
+ let mut lines = text.lines().map(|l| {
+ stripped_filtered_line(l).unwrap_or(l)
+ });
let text = lines.collect::<Vec<&str>>().connect("\n");
tests.add_test(text, should_fail, no_run, ignore);
})
}
}
- extern fn header(_ob: *buf, text: *buf, level: libc::c_int, opaque: *libc::c_void) {
+
+ extern fn header(_ob: *mut hoedown_buffer, text: *hoedown_buffer,
+ level: libc::c_int, opaque: *mut libc::c_void) {
unsafe {
- let tests = &mut *(opaque as *mut ::test::Collector);
+ let opaque = opaque as *mut hoedown_html_renderer_state;
+ let tests = &mut *((*opaque).opaque as *mut ::test::Collector);
if text.is_null() {
tests.register_header("", level as u32);
} else {
}
unsafe {
- let ob = bufnew(OUTPUT_UNIT);
- let extensions = MKDEXT_NO_INTRA_EMPHASIS | MKDEXT_TABLES |
- MKDEXT_FENCED_CODE | MKDEXT_AUTOLINK |
- MKDEXT_STRIKETHROUGH;
- let callbacks = sd_callbacks {
- blockcode: Some(block),
- blockquote: None,
- blockhtml: None,
- header: Some(header),
- other: mem::init()
- };
-
- let tests = tests as *mut ::test::Collector as *libc::c_void;
- let markdown = sd_markdown_new(extensions, 16, &callbacks, tests);
-
- sd_markdown_render(ob, doc.as_ptr(), doc.len() as libc::size_t,
- markdown);
- sd_markdown_free(markdown);
- bufrelease(ob);
+ let ob = hoedown_buffer_new(DEF_OUNIT);
+ let renderer = hoedown_html_renderer_new(0, 0);
+ (*renderer).blockcode = Some(block);
+ (*renderer).header = Some(header);
+ (*(*renderer).opaque).opaque = tests as *mut _ as *mut libc::c_void;
+
+ let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
+ hoedown_document_render(document, ob, doc.as_ptr(),
+ doc.len() as libc::size_t);
+ hoedown_document_free(document);
+
+ hoedown_html_renderer_free(renderer);
+ hoedown_buffer_free(ob);
}
}
// Add all the static files. These may already exist, but we just
// overwrite them anyway to make sure that they're fresh and up-to-date.
try!(write(cx.dst.join("jquery.js"),
- include_str!("static/jquery-2.1.0.min.js")));
- try!(write(cx.dst.join("main.js"), include_str!("static/main.js")));
- try!(write(cx.dst.join("main.css"), include_str!("static/main.css")));
+ include_bin!("static/jquery-2.1.0.min.js")));
+ try!(write(cx.dst.join("main.js"), include_bin!("static/main.js")));
+ try!(write(cx.dst.join("main.css"), include_bin!("static/main.css")));
try!(write(cx.dst.join("normalize.css"),
- include_str!("static/normalize.css")));
+ include_bin!("static/normalize.css")));
+ try!(write(cx.dst.join("FiraSans-Regular.woff"),
+ include_bin!("static/FiraSans-Regular.woff")));
+ try!(write(cx.dst.join("FiraSans-Medium.woff"),
+ include_bin!("static/FiraSans-Medium.woff")));
+ try!(write(cx.dst.join("Heuristica-Regular.woff"),
+ include_bin!("static/Heuristica-Regular.woff")));
+ try!(write(cx.dst.join("Heuristica-Italic.woff"),
+ include_bin!("static/Heuristica-Italic.woff")));
+ try!(write(cx.dst.join("Heuristica-Bold.woff"),
+ include_bin!("static/Heuristica-Bold.woff")));
// Update the search index
let dst = cx.dst.join("search-index.js");
/// Writes the entire contents of a string to a destination, not attempting to
/// catch any errors.
-fn write(dst: Path, contents: &str) -> io::IoResult<()> {
- File::create(&dst).write(contents.as_bytes())
+fn write(dst: Path, contents: &[u8]) -> io::IoResult<()> {
+ File::create(&dst).write(contents)
}
/// Makes a directory on the filesystem, failing the task if an error occurs and
clean::ModuleItem(..) => true, _ => false
}
}
+
+ fn link(&self) -> ~str {
+ let mut path = Vec::new();
+ clean_srcpath(self.item.source.filename.as_bytes(), |component| {
+ path.push(component.to_owned());
+ });
+ let href = if self.item.source.loline == self.item.source.hiline {
+ format!("{}", self.item.source.loline)
+ } else {
+ format!("{}-{}", self.item.source.loline, self.item.source.hiline)
+ };
+ format!("{root}src/{krate}/{path}.html\\#{href}",
+ root = self.cx.root_path,
+ krate = self.cx.layout.krate,
+ path = path.connect("/"),
+ href = href)
+ }
}
impl<'a> fmt::Show for Item<'a> {
// Write `src` tag
if self.cx.include_sources {
- let mut path = Vec::new();
- clean_srcpath(self.item.source.filename.as_bytes(), |component| {
- path.push(component.to_owned());
- });
- let href = if self.item.source.loline == self.item.source.hiline {
- format!("{}", self.item.source.loline)
- } else {
- format!("{}-{}", self.item.source.loline, self.item.source.hiline)
- };
- try!(write!(fmt.buf,
- "<a class='source' \
- href='{root}src/{krate}/{path}.html\\#{href}'>\
- [src]</a>",
- root = self.cx.root_path,
- krate = self.cx.layout.krate,
- path = path.connect("/"),
- href = href));
+ try!(write!(fmt.buf, "<a class='source' href='{}'>[src]</a>",
+ self.link()));
}
try!(write!(fmt.buf, "</h1>\n"));
match myitem.inner {
clean::StaticItem(ref s) | clean::ForeignStaticItem(ref s) => {
- struct Initializer<'a>(&'a str);
+ struct Initializer<'a>(&'a str, Item<'a>);
impl<'a> fmt::Show for Initializer<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let Initializer(s) = *self;
+ let Initializer(s, item) = *self;
if s.len() == 0 { return Ok(()); }
try!(write!(f.buf, "<code> = </code>"));
- let tag = if s.contains("\n") { "pre" } else { "code" };
- try!(write!(f.buf, "<{tag}>{}</{tag}>",
- s.as_slice(), tag=tag));
- Ok(())
+ if s.contains("\n") {
+ write!(f.buf,
+ "<a href='{}'>[definition]</a>",
+ item.link())
+ } else {
+ write!(f.buf, "<code>{}</code>", s.as_slice())
+ }
}
}
VisSpace(myitem.visibility),
*myitem.name.get_ref(),
s.type_,
- Initializer(s.expr),
+ Initializer(s.expr, Item { cx: cx, item: myitem }),
Markdown(blank(myitem.doc_value()))));
}
None => {}
}
- fn docmeth(w: &mut Writer, item: &clean::Item) -> io::IoResult<bool> {
+ fn docmeth(w: &mut Writer, item: &clean::Item,
+ dox: bool) -> io::IoResult<()> {
try!(write!(w, "<h4 id='method.{}' class='method'><code>",
*item.name.get_ref()));
try!(render_method(w, item));
try!(write!(w, "</code></h4>\n"));
match item.doc_value() {
- Some(s) => {
+ Some(s) if dox => {
try!(write!(w, "<div class='docblock'>{}</div>", Markdown(s)));
- Ok(true)
+ Ok(())
}
- None => Ok(false)
+ Some(..) | None => Ok(())
}
}
try!(write!(w, "<div class='methods'>"));
for meth in i.methods.iter() {
- if try!(docmeth(w, meth)) {
- continue
- }
-
- // No documentation? Attempt to slurp in the trait's documentation
- let trait_id = match trait_id {
- None => continue,
- Some(id) => id,
- };
- try!(local_data::get(cache_key, |cache| {
- let cache = cache.unwrap();
- match cache.traits.find(&trait_id) {
- Some(t) => {
- let name = meth.name.clone();
- match t.methods.iter().find(|t| t.item().name == name) {
- Some(method) => {
- match method.item().doc_value() {
- Some(s) => {
- try!(write!(w,
- "<div class='docblock'>{}</div>",
- Markdown(s)));
- }
- None => {}
- }
- }
- None => {}
- }
- }
- None => {}
- }
- Ok(())
- }))
+ try!(docmeth(w, meth, true));
}
// If we've implemented a trait, then also emit documentation for all
None => {}
}
- try!(docmeth(w, method.item()));
+ try!(docmeth(w, method.item(), false));
}
}
None => {}
use passes;
use visit_ast::RustdocVisitor;
-pub fn run(input: &str, cfgs: Vec<~str>,
- libs: HashSet<Path>, mut test_args: Vec<~str>) -> int {
+pub fn run(input: &str,
+ cfgs: Vec<~str>,
+ libs: HashSet<Path>,
+ mut test_args: Vec<~str>)
+ -> int {
let input_path = Path::new(input);
let input = driver::FileInput(input_path.clone());
diagnostic::mk_span_handler(diagnostic_handler, codemap);
let sess = driver::build_session_(sessopts,
- Some(input_path),
+ Some(input_path.clone()),
span_diagnostic_handler);
let mut cfg = driver::build_configuration(&sess);
let ctx = @core::DocContext {
krate: krate,
maybe_typed: core::NotTyped(sess),
+ src: input_path,
};
local_data::set(super::ctxtkey, ctx);
addl_lib_search_paths: RefCell::new(libs),
crate_types: vec!(session::CrateTypeExecutable),
output_types: vec!(link::OutputTypeExe),
+ no_trans: no_run,
cg: session::CodegenOptions {
prefer_dynamic: true,
.. session::basic_codegen_options()
let old = io::stdio::set_stderr(box w1);
spawn(proc() {
let mut p = io::ChanReader::new(rx);
- let mut err = old.unwrap_or(box io::stderr() as ~Writer:Send);
+ let mut err = old.unwrap_or(box io::stderr() as Box<Writer:Send>);
io::util::copy(&mut p, &mut err).unwrap();
});
let emitter = diagnostic::EmitterWriter::new(box w2);
use syntax::ast;
use syntax::ast_util;
use syntax::ast_map;
+use syntax::attr::AttrMetaMethods;
use syntax::codemap::Span;
use core;
if item.vis != ast::Public {
return om.view_items.push(item.clone());
}
+ let please_inline = item.attrs.iter().any(|item| {
+ match item.meta_item_list() {
+ Some(list) => {
+ list.iter().any(|i| i.name().get() == "inline")
+ }
+ None => false,
+ }
+ });
let item = match item.node {
ast::ViewItemUse(ref vpath) => {
- match self.visit_view_path(*vpath, om) {
+ match self.visit_view_path(*vpath, om, please_inline) {
None => return,
Some(path) => {
ast::ViewItem {
}
fn visit_view_path(&mut self, path: @ast::ViewPath,
- om: &mut Module) -> Option<@ast::ViewPath> {
+ om: &mut Module,
+ please_inline: bool) -> Option<@ast::ViewPath> {
match path.node {
ast::ViewPathSimple(_, _, id) => {
- if self.resolve_id(id, false, om) { return None }
+ if self.resolve_id(id, false, om, please_inline) { return None }
}
ast::ViewPathList(ref p, ref paths, ref b) => {
let mut mine = Vec::new();
for path in paths.iter() {
- if !self.resolve_id(path.node.id, false, om) {
+ if !self.resolve_id(path.node.id, false, om, please_inline) {
mine.push(path.clone());
}
}
// these are feature gated anyway
ast::ViewPathGlob(_, id) => {
- if self.resolve_id(id, true, om) { return None }
+ if self.resolve_id(id, true, om, please_inline) { return None }
}
}
return Some(path);
}
fn resolve_id(&mut self, id: ast::NodeId, glob: bool,
- om: &mut Module) -> bool {
+ om: &mut Module, please_inline: bool) -> bool {
let tcx = match self.cx.maybe_typed {
core::Typed(ref tcx) => tcx,
core::NotTyped(_) => return false
let analysis = match self.analysis {
Some(analysis) => analysis, None => return false
};
- if analysis.public_items.contains(&def.node) { return false }
+ if !please_inline && analysis.public_items.contains(&def.node) {
+ return false
+ }
match tcx.map.get(def.node) {
ast_map::NodeItem(it) => {
/// (the uv event loop).
use std::cast;
-use std::sync::arc::UnsafeArc;
-use std::rt::task::{BlockedTask, Task};
use std::rt::local::Local;
+use std::rt::task::{BlockedTask, Task};
+use std::sync::arc::UnsafeArc;
use homing::HomingMissile;
let inner: &mut Inner = unsafe { cast::transmute(self.inner.get()) };
if inner.held {
- let t: ~Task = Local::take();
+ let t: Box<Task> = Local::take();
t.deschedule(1, |task| {
inner.queue.push(task);
Ok(())
}
struct Payload {
- callback: ~Callback:Send,
+ callback: Box<Callback:Send>,
exit_flag: Exclusive<bool>,
}
impl AsyncWatcher {
- pub fn new(loop_: &mut Loop, cb: ~Callback:Send) -> AsyncWatcher {
+ pub fn new(loop_: &mut Loop, cb: Box<Callback:Send>) -> AsyncWatcher {
let handle = UvHandle::alloc(None::<AsyncWatcher>, uvll::UV_ASYNC);
assert_eq!(unsafe {
uvll::uv_async_init(loop_.handle, handle, async_cb)
extern fn close_cb(handle: *uvll::uv_handle_t) {
// drop the payload
- let _payload: ~Payload = unsafe {
+ let _payload: Box<Payload> = unsafe {
cast::transmute(uvll::get_data_for_uv_handle(handle))
};
// and then free the handle
path: path,
size: stat.st_size as u64,
kind: kind,
- perm: (stat.st_mode as io::FilePermission) & io::AllPermissions,
+ perm: unsafe {
+ io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
+ },
created: to_msec(stat.st_birthtim),
modified: to_msec(stat.st_mtim),
accessed: to_msec(stat.st_atim),
// to go (remember we have no preemption, so we're guaranteed to stay on
// this event loop as long as we avoid the scheduler).
if cur_loop_id != destination {
- let cur_task: ~Task = Local::take();
+ let cur_task: Box<Task> = Local::take();
cur_task.deschedule(1, |task| {
self.home().send(task);
Ok(())
handle: *uvll::uv_idle_t,
idle_flag: bool,
closed: bool,
- callback: ~Callback:Send,
+ callback: Box<Callback:Send>,
}
impl IdleWatcher {
- pub fn new(loop_: &mut Loop, cb: ~Callback:Send) -> ~IdleWatcher {
+ pub fn new(loop_: &mut Loop, cb: Box<Callback:Send>) -> Box<IdleWatcher> {
let handle = UvHandle::alloc(None::<IdleWatcher>, uvll::UV_IDLE);
assert_eq!(unsafe {
uvll::uv_idle_init(loop_.handle, handle)
extern fn onetime_cb(handle: *uvll::uv_idle_t) {
unsafe {
let data = uvll::get_data_for_uv_handle(handle);
- let f: ~proc() = cast::transmute(data);
+ let f: Box<proc()> = cast::transmute(data);
(*f)();
assert_eq!(uvll::uv_idle_stop(handle), 0);
uvll::uv_close(handle, close_cb);
}
}
- fn mk(v: uint) -> (~IdleWatcher, Chan) {
+ fn mk(v: uint) -> (Box<IdleWatcher>, Chan) {
let rc = Rc::new(RefCell::new((None, 0)));
let cb = box MyCallback(rc.clone(), v);
- let cb = cb as ~Callback:;
+ let cb = cb as Box<Callback:>;
let cb = unsafe { cast::transmute(cb) };
(IdleWatcher::new(&mut local_loop().loop_, cb), rc)
}
fn sleep(chan: &Chan) -> uint {
- let task: ~Task = Local::take();
+ let task: Box<Task> = Local::take();
task.deschedule(1, |task| {
match *chan.borrow_mut().deref_mut() {
(ref mut slot, _) => {
#[cfg(test)] extern crate realrustuv = "rustuv";
extern crate libc;
+use libc::{c_int, c_void};
use std::cast;
use std::fmt;
use std::io::IoError;
use std::io;
-use libc::{c_int, c_void};
use std::ptr::null;
use std::ptr;
use std::rt::local::Local;
/// // this code is running inside of a green task powered by libuv
/// }
/// ```
-pub fn event_loop() -> ~rtio::EventLoop:Send {
- box uvio::UvEventLoop::new() as ~rtio::EventLoop:Send
+pub fn event_loop() -> Box<rtio::EventLoop:Send> {
+ box uvio::UvEventLoop::new() as Box<rtio::EventLoop:Send>
}
/// A type that wraps a uv handle
cast::transmute(uvll::get_data_for_uv_handle(*h))
}
- fn install(~self) -> ~Self {
+ fn install(~self) -> Box<Self> {
unsafe {
- let myptr = cast::transmute::<&~Self, &*u8>(&self);
+ let myptr = cast::transmute::<&Box<Self>, &*u8>(&self);
uvll::set_data_for_uv_handle(self.uv_handle(), *myptr);
}
self
let _f = ForbidUnwind::new("wait_until_woken_after");
unsafe {
assert!((*slot).is_none());
- let task: ~Task = Local::take();
+ let task: Box<Task> = Local::take();
loop_.modify_blockers(1);
task.deschedule(1, |task| {
*slot = Some(task);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use libc::{size_t, ssize_t, c_int, c_void, c_uint};
+use libc;
use std::cast;
use std::io::{IoError, IoResult};
use std::io::net::ip;
-use libc::{size_t, ssize_t, c_int, c_void, c_uint};
-use libc;
use std::mem;
use std::ptr;
use std::rt::rtio;
pub struct ConnectCtx {
pub status: c_int,
pub task: Option<BlockedTask>,
- pub timer: Option<~TimerWatcher>,
+ pub timer: Option<Box<TimerWatcher>>,
}
pub struct AcceptTimeout {
home: HomeHandle,
handle: *uvll::uv_pipe_t,
closing_task: Option<BlockedTask>,
- outgoing: Sender<Result<~rtio::RtioTcpStream:Send, IoError>>,
- incoming: Receiver<Result<~rtio::RtioTcpStream:Send, IoError>>,
+ outgoing: Sender<Result<Box<rtio::RtioTcpStream:Send>, IoError>>,
+ incoming: Receiver<Result<Box<rtio::RtioTcpStream:Send>, IoError>>,
}
pub struct TcpAcceptor {
- listener: ~TcpListener,
+ listener: Box<TcpListener>,
timeout: AcceptTimeout,
}
})
}
- fn clone(&self) -> ~rtio::RtioTcpStream:Send {
+ fn clone(&self) -> Box<rtio::RtioTcpStream:Send> {
box TcpWatcher {
handle: self.handle,
stream: StreamWatcher::new(self.handle),
refcount: self.refcount.clone(),
write_access: self.write_access.clone(),
read_access: self.read_access.clone(),
- } as ~rtio::RtioTcpStream:Send
+ } as Box<rtio::RtioTcpStream:Send>
}
fn close_write(&mut self) -> Result<(), IoError> {
impl TcpListener {
pub fn bind(io: &mut UvIoFactory, address: ip::SocketAddr)
- -> Result<~TcpListener, UvError> {
+ -> Result<Box<TcpListener>, UvError> {
let handle = unsafe { uvll::malloc_handle(uvll::UV_TCP) };
assert_eq!(unsafe {
uvll::uv_tcp_init(io.uv_loop(), handle)
}
impl rtio::RtioTcpListener for TcpListener {
- fn listen(~self) -> Result<~rtio::RtioTcpAcceptor:Send, IoError> {
+ fn listen(~self) -> Result<Box<rtio::RtioTcpAcceptor:Send>, IoError> {
// create the acceptor object from ourselves
let mut acceptor = box TcpAcceptor {
listener: self,
let _m = acceptor.fire_homing_missile();
// FIXME: the 128 backlog should be configurable
match unsafe { uvll::uv_listen(acceptor.listener.handle, 128, listen_cb) } {
- 0 => Ok(acceptor as ~rtio::RtioTcpAcceptor:Send),
+ 0 => Ok(acceptor as Box<rtio::RtioTcpAcceptor:Send>),
n => Err(uv_error_to_io_error(UvError(n))),
}
}
});
let client = TcpWatcher::new_home(&loop_, tcp.home().clone());
assert_eq!(unsafe { uvll::uv_accept(server, client.handle) }, 0);
- Ok(box client as ~rtio::RtioTcpStream:Send)
+ Ok(box client as Box<rtio::RtioTcpStream:Send>)
}
n => Err(uv_error_to_io_error(UvError(n)))
};
}
impl rtio::RtioTcpAcceptor for TcpAcceptor {
- fn accept(&mut self) -> Result<~rtio::RtioTcpStream:Send, IoError> {
+ fn accept(&mut self) -> Result<Box<rtio::RtioTcpStream:Send>, IoError> {
self.timeout.accept(&self.listener.incoming)
}
})
}
- fn clone(&self) -> ~rtio::RtioUdpSocket:Send {
+ fn clone(&self) -> Box<rtio::RtioUdpSocket:Send> {
box UdpWatcher {
handle: self.handle,
home: self.home.clone(),
refcount: self.refcount.clone(),
write_access: self.write_access.clone(),
read_access: self.read_access.clone(),
- } as ~rtio::RtioUdpSocket:Send
+ } as Box<rtio::RtioUdpSocket:Send>
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use libc;
use std::c_str::CString;
use std::io::IoError;
-use libc;
use std::rt::rtio::{RtioPipe, RtioUnixListener, RtioUnixAcceptor};
use access::Access;
pub struct PipeListener {
home: HomeHandle,
pipe: *uvll::uv_pipe_t,
- outgoing: Sender<Result<~RtioPipe:Send, IoError>>,
- incoming: Receiver<Result<~RtioPipe:Send, IoError>>,
+ outgoing: Sender<Result<Box<RtioPipe:Send>, IoError>>,
+ incoming: Receiver<Result<Box<RtioPipe:Send>, IoError>>,
}
pub struct PipeAcceptor {
- listener: ~PipeListener,
+ listener: Box<PipeListener>,
timeout: net::AcceptTimeout,
}
self.stream.write(buf).map_err(uv_error_to_io_error)
}
- fn clone(&self) -> ~RtioPipe:Send {
+ fn clone(&self) -> Box<RtioPipe:Send> {
box PipeWatcher {
stream: StreamWatcher::new(self.stream.handle),
defused: false,
refcount: self.refcount.clone(),
read_access: self.read_access.clone(),
write_access: self.write_access.clone(),
- } as ~RtioPipe:Send
+ } as Box<RtioPipe:Send>
}
}
impl PipeListener {
pub fn bind(io: &mut UvIoFactory, name: &CString)
- -> Result<~PipeListener, UvError>
+ -> Result<Box<PipeListener>, UvError>
{
let pipe = PipeWatcher::new(io, false);
match unsafe {
}
impl RtioUnixListener for PipeListener {
- fn listen(~self) -> Result<~RtioUnixAcceptor:Send, IoError> {
+ fn listen(~self) -> Result<Box<RtioUnixAcceptor:Send>, IoError> {
// create the acceptor object from ourselves
let mut acceptor = box PipeAcceptor {
listener: self,
let _m = acceptor.fire_homing_missile();
// FIXME: the 128 backlog should be configurable
match unsafe { uvll::uv_listen(acceptor.listener.pipe, 128, listen_cb) } {
- 0 => Ok(acceptor as ~RtioUnixAcceptor:Send),
+ 0 => Ok(acceptor as Box<RtioUnixAcceptor:Send>),
n => Err(uv_error_to_io_error(UvError(n))),
}
}
});
let client = PipeWatcher::new_home(&loop_, pipe.home().clone(), false);
assert_eq!(unsafe { uvll::uv_accept(server, client.handle()) }, 0);
- Ok(box client as ~RtioPipe:Send)
+ Ok(box client as Box<RtioPipe:Send>)
}
n => Err(uv_error_to_io_error(UvError(n)))
};
// PipeAcceptor implementation and traits
impl RtioUnixAcceptor for PipeAcceptor {
- fn accept(&mut self) -> Result<~RtioPipe:Send, IoError> {
+ fn accept(&mut self) -> Result<Box<RtioPipe:Send>, IoError> {
self.timeout.accept(&self.listener.incoming)
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::io::IoError;
-use std::io::process;
use libc::c_int;
use libc;
+use std::io::IoError;
+use std::io::process;
use std::ptr;
use std::rt::rtio::RtioProcess;
use std::rt::task::BlockedTask;
/// Returns either the corresponding process object or an error which
/// occurred.
pub fn spawn(io_loop: &mut UvIoFactory, config: process::ProcessConfig)
- -> Result<(~Process, ~[Option<PipeWatcher>]), UvError>
- {
+ -> Result<(Box<Process>, ~[Option<PipeWatcher>]), UvError> {
let cwd = config.cwd.map(|s| s.to_c_str());
let mut io = vec![config.stdin, config.stdout, config.stderr];
for slot in config.extra_io.iter() {
#![allow(dead_code)]
-use std::cast;
use libc::c_void;
+use std::cast;
use std::rt::task::BlockedTask;
use std::unstable::mutex::NativeMutex;
use std::sync::arc::UnsafeArc;
}
impl QueuePool {
- pub fn new(loop_: &mut Loop) -> ~QueuePool {
+ pub fn new(loop_: &mut Loop) -> Box<QueuePool> {
let handle = UvHandle::alloc(None::<AsyncWatcher>, uvll::UV_ASYNC);
let state = UnsafeArc::new(State {
handle: handle,
}
impl SignalWatcher {
- pub fn new(io: &mut UvIoFactory, signum: Signum,
- channel: Sender<Signum>) -> Result<~SignalWatcher, UvError> {
+ pub fn new(io: &mut UvIoFactory, signum: Signum, channel: Sender<Signum>)
+ -> Result<Box<SignalWatcher>, UvError> {
let s = box SignalWatcher {
handle: UvHandle::alloc(None::<SignalWatcher>, uvll::UV_SIGNAL),
home: io.make_handle(),
}
impl TimerWatcher {
- pub fn new(io: &mut UvIoFactory) -> ~TimerWatcher {
+ pub fn new(io: &mut UvIoFactory) -> Box<TimerWatcher> {
let handle = io.make_handle();
let me = box TimerWatcher::new_home(&io.loop_, handle);
me.install()
IdleWatcher::onetime(&mut self.uvio.loop_, f);
}
- fn pausable_idle_callback(&mut self, cb: ~rtio::Callback:Send)
- -> ~rtio::PausableIdleCallback:Send
- {
- IdleWatcher::new(&mut self.uvio.loop_,
- cb) as ~rtio::PausableIdleCallback:Send
+ fn pausable_idle_callback(&mut self, cb: Box<rtio::Callback:Send>)
+ -> Box<rtio::PausableIdleCallback:Send> {
+ IdleWatcher::new(&mut self.uvio.loop_, cb)
+ as Box<rtio::PausableIdleCallback:Send>
}
- fn remote_callback(&mut self, f: ~rtio::Callback:Send)
- -> ~rtio::RemoteCallback:Send
- {
- box AsyncWatcher::new(&mut self.uvio.loop_, f) as ~rtio::RemoteCallback:Send
+ fn remote_callback(&mut self, f: Box<rtio::Callback:Send>)
+ -> Box<rtio::RemoteCallback:Send> {
+ box AsyncWatcher::new(&mut self.uvio.loop_, f) as
+ Box<rtio::RemoteCallback:Send>
}
fn io<'a>(&'a mut self) -> Option<&'a mut rtio::IoFactory> {
pub struct UvIoFactory {
pub loop_: Loop,
- handle_pool: Option<~QueuePool>,
+ handle_pool: Option<Box<QueuePool>>,
}
impl UvIoFactory {
// NB: This blocks the task waiting on the connection.
// It would probably be better to return a future
fn tcp_connect(&mut self, addr: SocketAddr, timeout: Option<u64>)
- -> Result<~rtio::RtioTcpStream:Send, IoError>
- {
+ -> Result<Box<rtio::RtioTcpStream:Send>, IoError> {
match TcpWatcher::connect(self, addr, timeout) {
- Ok(t) => Ok(box t as ~rtio::RtioTcpStream:Send),
+ Ok(t) => Ok(box t as Box<rtio::RtioTcpStream:Send>),
Err(e) => Err(uv_error_to_io_error(e)),
}
}
- fn tcp_bind(&mut self, addr: SocketAddr) -> Result<~rtio::RtioTcpListener:Send, IoError> {
+ fn tcp_bind(&mut self, addr: SocketAddr)
+ -> Result<Box<rtio::RtioTcpListener:Send>, IoError> {
match TcpListener::bind(self, addr) {
- Ok(t) => Ok(t as ~rtio::RtioTcpListener:Send),
+ Ok(t) => Ok(t as Box<rtio::RtioTcpListener:Send>),
Err(e) => Err(uv_error_to_io_error(e)),
}
}
- fn udp_bind(&mut self, addr: SocketAddr) -> Result<~rtio::RtioUdpSocket:Send, IoError> {
+ fn udp_bind(&mut self, addr: SocketAddr)
+ -> Result<Box<rtio::RtioUdpSocket:Send>, IoError> {
match UdpWatcher::bind(self, addr) {
- Ok(u) => Ok(box u as ~rtio::RtioUdpSocket:Send),
+ Ok(u) => Ok(box u as Box<rtio::RtioUdpSocket:Send>),
Err(e) => Err(uv_error_to_io_error(e)),
}
}
- fn timer_init(&mut self) -> Result<~rtio::RtioTimer:Send, IoError> {
- Ok(TimerWatcher::new(self) as ~rtio::RtioTimer:Send)
+ fn timer_init(&mut self) -> Result<Box<rtio::RtioTimer:Send>, IoError> {
+ Ok(TimerWatcher::new(self) as Box<rtio::RtioTimer:Send>)
}
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
r.map_err(uv_error_to_io_error)
}
- fn fs_from_raw_fd(&mut self, fd: c_int,
- close: rtio::CloseBehavior) -> ~rtio::RtioFileStream:Send {
- box FileWatcher::new(self, fd, close) as ~rtio::RtioFileStream:Send
+ fn fs_from_raw_fd(&mut self, fd: c_int, close: rtio::CloseBehavior)
+ -> Box<rtio::RtioFileStream:Send> {
+ box FileWatcher::new(self, fd, close) as
+ Box<rtio::RtioFileStream:Send>
}
fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
- -> Result<~rtio::RtioFileStream:Send, IoError> {
+ -> Result<Box<rtio::RtioFileStream:Send>, IoError> {
let flags = match fm {
io::Open => 0,
io::Append => libc::O_APPEND,
};
match FsRequest::open(self, path, flags as int, mode as int) {
- Ok(fs) => Ok(box fs as ~rtio::RtioFileStream:Send),
+ Ok(fs) => Ok(box fs as Box<rtio::RtioFileStream:Send>),
Err(e) => Err(uv_error_to_io_error(e))
}
}
}
fn fs_mkdir(&mut self, path: &CString,
perm: io::FilePermission) -> Result<(), IoError> {
- let r = FsRequest::mkdir(&self.loop_, path, perm as c_int);
+ let r = FsRequest::mkdir(&self.loop_, path, perm.bits() as c_int);
r.map_err(uv_error_to_io_error)
}
fn fs_rmdir(&mut self, path: &CString) -> Result<(), IoError> {
}
fn fs_chmod(&mut self, path: &CString,
perm: io::FilePermission) -> Result<(), IoError> {
- let r = FsRequest::chmod(&self.loop_, path, perm as c_int);
+ let r = FsRequest::chmod(&self.loop_, path, perm.bits() as c_int);
r.map_err(uv_error_to_io_error)
}
fn fs_readdir(&mut self, path: &CString, flags: c_int)
}
fn spawn(&mut self, config: ProcessConfig)
- -> Result<(~rtio::RtioProcess:Send, ~[Option<~rtio::RtioPipe:Send>]), IoError>
+ -> Result<(Box<rtio::RtioProcess:Send>,
+ ~[Option<Box<rtio::RtioPipe:Send>>]),
+ IoError>
{
match Process::spawn(self, config) {
Ok((p, io)) => {
- Ok((p as ~rtio::RtioProcess:Send,
- io.move_iter().map(|i| i.map(|p| box p as ~rtio::RtioPipe:Send)).collect()))
+ Ok((p as Box<rtio::RtioProcess:Send>,
+ io.move_iter().map(|i| i.map(|p| {
+ box p as Box<rtio::RtioPipe:Send>
+ })).collect()))
}
Err(e) => Err(uv_error_to_io_error(e)),
}
Process::kill(pid, signum).map_err(uv_error_to_io_error)
}
- fn unix_bind(&mut self, path: &CString) -> Result<~rtio::RtioUnixListener:Send, IoError>
- {
+ fn unix_bind(&mut self, path: &CString)
+ -> Result<Box<rtio::RtioUnixListener:Send>, IoError> {
match PipeListener::bind(self, path) {
- Ok(p) => Ok(p as ~rtio::RtioUnixListener:Send),
+ Ok(p) => Ok(p as Box<rtio::RtioUnixListener:Send>),
Err(e) => Err(uv_error_to_io_error(e)),
}
}
- fn unix_connect(&mut self, path: &CString,
- timeout: Option<u64>) -> Result<~rtio::RtioPipe:Send, IoError> {
+ fn unix_connect(&mut self, path: &CString, timeout: Option<u64>)
+ -> Result<Box<rtio::RtioPipe:Send>, IoError> {
match PipeWatcher::connect(self, path, timeout) {
- Ok(p) => Ok(box p as ~rtio::RtioPipe:Send),
+ Ok(p) => Ok(box p as Box<rtio::RtioPipe:Send>),
Err(e) => Err(uv_error_to_io_error(e)),
}
}
fn tty_open(&mut self, fd: c_int, readable: bool)
- -> Result<~rtio::RtioTTY:Send, IoError> {
+ -> Result<Box<rtio::RtioTTY:Send>, IoError> {
match TtyWatcher::new(self, fd, readable) {
- Ok(tty) => Ok(box tty as ~rtio::RtioTTY:Send),
+ Ok(tty) => Ok(box tty as Box<rtio::RtioTTY:Send>),
Err(e) => Err(uv_error_to_io_error(e))
}
}
- fn pipe_open(&mut self, fd: c_int) -> Result<~rtio::RtioPipe:Send, IoError> {
+ fn pipe_open(&mut self, fd: c_int)
+ -> Result<Box<rtio::RtioPipe:Send>, IoError> {
match PipeWatcher::open(self, fd) {
- Ok(s) => Ok(box s as ~rtio::RtioPipe:Send),
+ Ok(s) => Ok(box s as Box<rtio::RtioPipe:Send>),
Err(e) => Err(uv_error_to_io_error(e))
}
}
fn signal(&mut self, signum: Signum, channel: Sender<Signum>)
- -> Result<~rtio::RtioSignal:Send, IoError> {
+ -> Result<Box<rtio::RtioSignal:Send>, IoError> {
match SignalWatcher::new(self, signum, channel) {
- Ok(s) => Ok(s as ~rtio::RtioSignal:Send),
+ Ok(s) => Ok(s as Box<rtio::RtioSignal:Send>),
Err(e) => Err(uv_error_to_io_error(e)),
}
}
impl ToJson for MyStruct {
fn to_json( &self ) -> json::Json {
- let mut d = ~TreeMap::new();
+ let mut d = box TreeMap::new();
d.insert("attr1".to_owned(), self.attr1.to_json());
d.insert("attr2".to_owned(), self.attr2.to_json());
json::Object(d)
impl ToJson for TestStruct1 {
fn to_json( &self ) -> json::Json {
- let mut d = ~TreeMap::new();
+ let mut d = box TreeMap::new();
d.insert("data_int".to_owned(), self.data_int.to_json());
d.insert("data_str".to_owned(), self.data_str.to_json());
d.insert("data_vector".to_owned(), self.data_vector.to_json());
*/
-use collections::HashMap;
use std::char;
use std::f64;
+use std::fmt;
use std::io::MemWriter;
use std::io;
+use std::mem::swap;
use std::num;
-use std::str;
use std::str::ScalarValue;
+use std::str;
use std::strbuf::StrBuf;
-use std::fmt;
use std::vec::Vec;
-use std::mem::swap;
use Encodable;
-use collections::TreeMap;
+use collections::{HashMap, TreeMap};
/// Represents a json value
#[deriving(Clone, Eq)]
String(~str),
Boolean(bool),
List(List),
- Object(~Object),
+ Object(Box<Object>),
Null,
}
}
}
-impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for ~T {
+impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for Box<T> {
fn encode(&self, s: &mut S) -> Result<(), E> {
(**self).encode(s)
}
}
-impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for ~T {
- fn decode(d: &mut D) -> Result<~T, E> {
+impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Box<T> {
+ fn decode(d: &mut D) -> Result<Box<T>, E> {
Ok(box try!(Decodable::decode(d)))
}
}
//! As `&Any` (a borrowed trait object), it has the `is` and `as_ref` methods, to test if the
//! contained value is of a given type, and to get a reference to the inner value as a type. As
//! `&mut Any`, there is also the `as_mut` method, for getting a mutable reference to the inner
-//! value. `~Any` adds the `move` method, which will unwrap a `~T` from the object. See the
-//! extension traits (`*Ext`) for the full details.
+//! value. `Box<Any>` adds the `move` method, which will unwrap a `Box<T>` from the object. See
+//! the extension traits (`*Ext`) for the full details.
use cast::{transmute, transmute_copy};
use fmt;
use option::{Option, Some, None};
+use owned::Box;
use raw::TraitObject;
use result::{Result, Ok, Err};
use intrinsics::TypeId;
pub trait AnyOwnExt {
/// Returns the boxed value if it is of type `T`, or
/// `Err(Self)` if it isn't.
- fn move<T: 'static>(self) -> Result<~T, Self>;
+ fn move<T: 'static>(self) -> Result<Box<T>, Self>;
}
-impl AnyOwnExt for ~Any {
+impl AnyOwnExt for Box<Any> {
#[inline]
- fn move<T: 'static>(self) -> Result<~T, ~Any> {
+ fn move<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
if self.is::<T>() {
unsafe {
// Get the raw representation of the trait object
// Trait implementations
///////////////////////////////////////////////////////////////////////////////
-impl fmt::Show for ~Any {
+impl fmt::Show for Box<Any> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.pad("~Any")
+ f.pad("Box<Any>")
}
}
mod tests {
use prelude::*;
use super::*;
+ use owned::Box;
use str::StrSlice;
#[deriving(Eq, Show)]
#[test]
fn any_owning() {
- let (a, b, c) = (box 5u as ~Any, box TEST as ~Any, box Test as ~Any);
+ let (a, b, c) = (box 5u as Box<Any>, box TEST as Box<Any>, box Test as Box<Any>);
assert!(a.is::<uint>());
assert!(!b.is::<uint>());
#[test]
fn any_move() {
- let a = box 8u as ~Any;
- let b = box Test as ~Any;
+ let a = box 8u as Box<Any>;
+ let b = box Test as Box<Any>;
match a.move::<uint>() {
Ok(a) => { assert_eq!(a, box 8u); }
Err(..) => fail!()
}
- let a = box 8u as ~Any;
- let b = box Test as ~Any;
+ let a = box 8u as Box<Any>;
+ let b = box Test as Box<Any>;
- assert!(a.move::<~Test>().is_err());
- assert!(b.move::<~uint>().is_err());
+ assert!(a.move::<Box<Test>>().is_err());
+ assert!(b.move::<Box<uint>>().is_err());
}
#[test]
fn test_show() {
- let a = box 8u as ~Any;
- let b = box Test as ~Any;
- assert_eq!(format!("{}", a), "~Any".to_owned());
- assert_eq!(format!("{}", b), "~Any".to_owned());
+ let a = box 8u as Box<Any>;
+ let b = box Test as Box<Any>;
+ assert_eq!(format!("{}", a), "Box<Any>".to_owned());
+ assert_eq!(format!("{}", b), "Box<Any>".to_owned());
let a = &8u as &Any;
let b = &Test as &Any;
//! # Example
//!
//! ~~~rust
-//! bitflags!(Flags: u32 {
-//! FlagA = 0x00000001,
-//! FlagB = 0x00000010,
-//! FlagC = 0x00000100,
-//! FlagABC = FlagA.bits
-//! | FlagB.bits
-//! | FlagC.bits
-//! })
+//! bitflags!(
+//! flags Flags: u32 {
+//! static FlagA = 0x00000001,
+//! static FlagB = 0x00000010,
+//! static FlagC = 0x00000100,
+//! static FlagABC = FlagA.bits
+//! | FlagB.bits
+//! | FlagC.bits
+//! }
+//! )
//!
//! fn main() {
//! let e1 = FlagA | FlagC;
//! ~~~rust
//! use std::fmt;
//!
-//! bitflags!(Flags: u32 {
-//! FlagA = 0x00000001,
-//! FlagB = 0x00000010
-//! })
+//! bitflags!(
+//! flags Flags: u32 {
+//! static FlagA = 0x00000001,
+//! static FlagB = 0x00000010
+//! }
+//! )
//!
//! impl Flags {
//! pub fn clear(&mut self) {
//! }
//! ~~~
//!
+//! # Attributes
+//!
+//! Attributes can be attached to the generated `struct` by placing them
+//! before the `flags` keyword.
+//!
//! # Derived traits
//!
-//! The `Eq`, `TotalEq`, and `Clone` traits are automatically derived for the
-//! `struct` using the `deriving` attribute.
+//! The `Eq` and `Clone` traits are automatically derived for the `struct` using
+//! the `deriving` attribute. Additional traits can be derived by providing an
+//! explicit `deriving` attribute on `flags`.
//!
//! # Operators
//!
//! - `insert`: inserts the specified flags in-place
//! - `remove`: removes the specified flags in-place
+#![macro_escape]
+
#[macro_export]
macro_rules! bitflags(
- ($BitFlags:ident: $T:ty {
- $($Flag:ident = $value:expr),+
+ ($(#[$attr:meta])* flags $BitFlags:ident: $T:ty {
+ $($(#[$Flag_attr:meta])* static $Flag:ident = $value:expr),+
}) => (
#[deriving(Eq, TotalEq, Clone)]
+ $(#[$attr])*
pub struct $BitFlags {
bits: $T,
}
- $(pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+
+ $($(#[$Flag_attr])* pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+
impl $BitFlags {
/// Returns an empty set of flags.
self.bits
}
+ /// Convert from underlying bit representation. Unsafe because the
+ /// bits are not guaranteed to represent valid flags.
+ pub unsafe fn from_bits(bits: $T) -> $BitFlags {
+ $BitFlags { bits: bits }
+ }
+
/// Returns `true` if no flags are currently stored.
pub fn is_empty(&self) -> bool {
*self == $BitFlags::empty()
mod tests {
use ops::{BitOr, BitAnd, Sub};
- bitflags!(Flags: u32 {
- FlagA = 0x00000001,
- FlagB = 0x00000010,
- FlagC = 0x00000100,
- FlagABC = FlagA.bits
- | FlagB.bits
- | FlagC.bits
- })
+ bitflags!(
+ flags Flags: u32 {
+ static FlagA = 0x00000001,
+ static FlagB = 0x00000010,
+ static FlagC = 0x00000100,
+ static FlagABC = FlagA.bits
+ | FlagB.bits
+ | FlagC.bits
+ }
+ )
#[test]
fn test_bits(){
unsafe { puts(c_buffer); }
});
}
- ```
+```
*/
*/
+use owned::Box;
+
/// A common trait for cloning an object.
pub trait Clone {
/// Returns a copy of the value. The contents of owned pointers
}
}
-impl<T: Clone> Clone for ~T {
+impl<T: Clone> Clone for Box<T> {
/// Return a copy of the owned box.
#[inline]
- fn clone(&self) -> ~T { box {(**self).clone()} }
+ fn clone(&self) -> Box<T> { box {(**self).clone()} }
/// Perform copy-assignment from `source` by reusing the existing allocation.
#[inline]
- fn clone_from(&mut self, source: &~T) {
+ fn clone_from(&mut self, source: &Box<T>) {
(**self).clone_from(&(**source));
}
}
#[test]
fn test_owned_clone() {
let a = box 5i;
- let b: ~int = a.clone();
+ let b: Box<int> = a.clone();
assert_eq!(a, b);
}
use mem;
use ops::Drop;
use option::{Some, None, Option};
+use owned::Box;
use result::{Ok, Err, Result};
use rt::local::Local;
use rt::task::{Task, BlockedTask};
use prelude::*;
use super::*;
use super::super::*;
+ use owned::Box;
use task;
fn f() $b
let cnt = self.sends.get() + 1;
self.sends.set(cnt);
if cnt % (RESCHED_FREQ as uint) == 0 {
- let task: Option<~Task> = Local::try_take();
+ let task: Option<Box<Task>> = Local::try_take();
task.map(|t| t.maybe_yield());
}
let cnt = self.receives.get() + 1;
self.receives.set(cnt);
if cnt % (RESCHED_FREQ as uint) == 0 {
- let task: Option<~Task> = Local::try_take();
+ let task: Option<Box<Task>> = Local::try_take();
task.map(|t| t.maybe_yield());
}
use native;
use os;
+ use owned::Box;
use super::*;
pub fn stress_factor() -> uint {
test!(fn oneshot_single_thread_send_port_close() {
// Testing that the sender cleans up the payload if receiver is closed
- let (tx, rx) = channel::<~int>();
+ let (tx, rx) = channel::<Box<int>>();
drop(rx);
tx.send(box 0);
} #[should_fail])
})
test!(fn oneshot_single_thread_send_then_recv() {
- let (tx, rx) = channel::<~int>();
+ let (tx, rx) = channel::<Box<int>>();
tx.send(box 10);
assert!(rx.recv() == box 10);
})
})
test!(fn oneshot_multi_task_recv_then_send() {
- let (tx, rx) = channel::<~int>();
+ let (tx, rx) = channel::<Box<int>>();
spawn(proc() {
assert!(rx.recv() == box 10);
});
})
test!(fn oneshot_multi_task_recv_then_close() {
- let (tx, rx) = channel::<~int>();
+ let (tx, rx) = channel::<Box<int>>();
spawn(proc() {
drop(tx);
});
send(tx, 0);
recv(rx, 0);
- fn send(tx: Sender<~int>, i: int) {
+ fn send(tx: Sender<Box<int>>, i: int) {
if i == 10 { return }
spawn(proc() {
});
}
- fn recv(rx: Receiver<~int>, i: int) {
+ fn recv(rx: Receiver<Box<int>>, i: int) {
if i == 10 { return }
spawn(proc() {
mod sync_tests {
use prelude::*;
use os;
+ use owned::Box;
pub fn stress_factor() -> uint {
match os::getenv("RUST_TEST_STRESS") {
test!(fn oneshot_single_thread_send_port_close() {
// Testing that the sender cleans up the payload if receiver is closed
- let (tx, rx) = sync_channel::<~int>(0);
+ let (tx, rx) = sync_channel::<Box<int>>(0);
drop(rx);
tx.send(box 0);
} #[should_fail])
})
test!(fn oneshot_single_thread_send_then_recv() {
- let (tx, rx) = sync_channel::<~int>(1);
+ let (tx, rx) = sync_channel::<Box<int>>(1);
tx.send(box 10);
assert!(rx.recv() == box 10);
})
})
test!(fn oneshot_multi_task_recv_then_send() {
- let (tx, rx) = sync_channel::<~int>(0);
+ let (tx, rx) = sync_channel::<Box<int>>(0);
spawn(proc() {
assert!(rx.recv() == box 10);
});
})
test!(fn oneshot_multi_task_recv_then_close() {
- let (tx, rx) = sync_channel::<~int>(0);
+ let (tx, rx) = sync_channel::<Box<int>>(0);
spawn(proc() {
drop(tx);
});
send(tx, 0);
recv(rx, 0);
- fn send(tx: SyncSender<~int>, i: int) {
+ fn send(tx: SyncSender<Box<int>>, i: int) {
if i == 10 { return }
spawn(proc() {
});
}
- fn recv(rx: Receiver<~int>, i: int) {
+ fn recv(rx: Receiver<Box<int>>, i: int) {
if i == 10 { return }
spawn(proc() {
use mem;
use ops::Drop;
use option::{Some, None, Option};
+use owned::Box;
use result::{Result, Ok, Err};
use rt::local::Local;
use rt::task::{Task, BlockedTask};
// Attempt to not block the task (it's a little expensive). If it looks
// like we're not empty, then immediately go through to `try_recv`.
if self.state.load(atomics::SeqCst) == EMPTY {
- let t: ~Task = Local::take();
+ let t: Box<Task> = Local::take();
t.deschedule(1, |task| {
let n = unsafe { task.cast_to_uint() };
match self.state.compare_and_swap(EMPTY, n, atomics::SeqCst) {
use kinds::Send;
use ops::Drop;
use option::{Some, None, Option};
+use owned::Box;
use ptr::RawPtr;
use result::{Ok, Err, Result};
use rt::local::Local;
// Acquire a number of blocking contexts, and block on each one
// sequentially until one fails. If one fails, then abort
// immediately so we can go unblock on all the other receivers.
- let task: ~Task = Local::take();
+ let task: Box<Task> = Local::take();
task.deschedule(amt, |task| {
// Prepare for the block
let (i, handle) = iter.next().unwrap();
use kinds::Send;
use ops::Drop;
use option::{Some, None, Option};
+use owned::Box;
use result::{Ok, Err, Result};
use rt::local::Local;
use rt::task::{Task, BlockedTask};
data => return data,
}
- let task: ~Task = Local::take();
+ let task: Box<Task> = Local::take();
task.deschedule(1, |task| {
self.decrement(task)
});
use kinds::Send;
use ops::Drop;
use option::{Some, None};
+use owned::Box;
use result::{Ok, Err, Result};
use rt::local::Local;
use rt::task::{Task, BlockedTask};
// Welp, our channel has no data. Deschedule the current task and
// initiate the blocking protocol.
- let task: ~Task = Local::take();
+ let task: Box<Task> = Local::take();
task.deschedule(1, |task| {
self.decrement(task)
});
use mem;
use ops::Drop;
use option::{Some, None, Option};
+use owned::Box;
use ptr::RawPtr;
use result::{Result, Ok, Err};
use rt::local::Local;
/// in the meantime. This re-locks the mutex upon returning.
fn wait(slot: &mut Blocker, f: fn(BlockedTask) -> Blocker,
lock: &NativeMutex) {
- let me: ~Task = Local::take();
+ let me: Box<Task> = Local::take();
me.deschedule(1, |task| {
match mem::replace(slot, f(task)) {
NoneBlocked => {}
impl Queue {
fn enqueue(&mut self, lock: &NativeMutex) {
- let task: ~Task = Local::take();
+ let task: Box<Task> = Local::take();
let mut node = Node {
task: None,
next: 0 as *mut Node,
//! The `Default` trait for types which may have meaningful default values
+use owned::Box;
+
/// A trait that types which have a useful default value should implement.
pub trait Default {
/// Return the "default value" for a type.
fn default() -> @T { @Default::default() }
}
-impl<T: Default> Default for ~T {
- fn default() -> ~T { box Default::default() }
+impl<T: Default> Default for Box<T> {
+ fn default() -> Box<T> { box Default::default() }
}
use iter::{Iterator, range};
use num::Signed;
use option::{Option,Some,None};
+use owned::Box;
use repr;
use result::{Ok, Err};
use str::StrSlice;
impl<T: Show> Show for @T {
fn fmt(&self, f: &mut Formatter) -> Result { secret_show(&**self, f) }
}
-impl<T: Show> Show for ~T {
+impl<T: Show> Show for Box<T> {
fn fmt(&self, f: &mut Formatter) -> Result { secret_show(&**self, f) }
}
impl<'a, T: Show> Show for &'a T {
use prelude::*;
use char;
+use owned::Box;
use str;
/// A piece is a portion of the format string which represents the next part
/// How to format the argument
pub format: FormatSpec<'a>,
/// If not `None`, what method to invoke on the argument
- pub method: Option<~Method<'a>>
+ pub method: Option<Box<Method<'a>>>
}
/// Specification for the formatting of an argument in the format string.
/// Parses a method to be applied to the previously specified argument and
/// its format. The two current supported methods are 'plural' and 'select'
- fn method(&mut self) -> Option<~Method<'a>> {
+ fn method(&mut self) -> Option<Box<Method<'a>>> {
if !self.wsconsume(',') {
return None;
}
}
/// Parses a 'select' statement (after the initial 'select' word)
- fn select(&mut self) -> ~Method<'a> {
+ fn select(&mut self) -> Box<Method<'a>> {
let mut other = None;
let mut arms = vec!();
// Consume arms one at a time
}
/// Parses a 'plural' statement (after the initial 'plural' word)
- fn plural(&mut self) -> ~Method<'a> {
+ fn plural(&mut self) -> Box<Method<'a>> {
let mut offset = None;
let mut other = None;
let mut arms = vec!();
use io::Writer;
use iter::Iterator;
use option::{Option, Some, None};
+use owned::Box;
use rc::Rc;
use str::{Str, StrSlice};
use slice::{Vector, ImmutableVector};
}
}
-impl<S: Writer, T: Hash<S>> Hash<S> for ~T {
+impl<S: Writer, T: Hash<S>> Hash<S> for Box<T> {
#[inline]
fn hash(&self, state: &mut S) {
(**self).hash(state);
use iter::Iterator;
use kinds::Send;
use super::{Reader, Writer, Seek};
-use super::{SeekStyle, Read, Write, Open, IoError, Truncate,
- FileMode, FileAccess, FileStat, IoResult, FilePermission};
+use super::{SeekStyle, Read, Write, Open, IoError, Truncate};
+use super::{FileMode, FileAccess, FileStat, IoResult, FilePermission};
use rt::rtio::{RtioFileStream, IoFactory, LocalIo};
use io;
use option::{Some, None, Option};
+use owned::Box;
use result::{Ok, Err};
use path;
use path::{Path, GenericPath};
/// configured at creation time, via the `FileAccess` parameter to
/// `File::open_mode()`.
pub struct File {
- fd: ~RtioFileStream:Send,
+ fd: Box<RtioFileStream:Send>,
path: Path,
last_nread: int,
}
check!(File::create(&input));
check!(chmod(&input, io::UserRead));
check!(copy(&input, &out));
- assert!(check!(out.stat()).perm & io::UserWrite == 0);
+ assert!(!check!(out.stat()).perm.intersects(io::UserWrite));
check!(chmod(&input, io::UserFile));
check!(chmod(&out, io::UserFile));
let file = tmpdir.join("in.txt");
check!(File::create(&file));
- assert!(check!(stat(&file)).perm & io::UserWrite == io::UserWrite);
+ assert!(check!(stat(&file)).perm.contains(io::UserWrite));
check!(chmod(&file, io::UserRead));
- assert!(check!(stat(&file)).perm & io::UserWrite == 0);
+ assert!(!check!(stat(&file)).perm.contains(io::UserWrite));
match chmod(&tmpdir.join("foo"), io::UserRWX) {
Ok(..) => fail!("wanted a failure"),
use int;
use iter::Iterator;
use libc;
+use ops::{BitOr, BitAnd, Sub};
use os;
use option::{Option, Some, None};
+use owned::Box;
use path::Path;
use result::{Ok, Err, Result};
use str::StrSlice;
}
}
-impl Reader for ~Reader {
+impl Reader for Box<Reader> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.read(buf) }
}
}
}
-impl Writer for ~Writer {
+impl Writer for Box<Writer> {
fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.write(buf) }
fn flush(&mut self) -> IoResult<()> { self.flush() }
}
pub gen: u64,
}
-/// A set of permissions for a file or directory is represented by a set of
-/// flags which are or'd together.
-pub type FilePermission = u32;
-
-// Each permission bit
-pub static UserRead: FilePermission = 0x100;
-pub static UserWrite: FilePermission = 0x080;
-pub static UserExecute: FilePermission = 0x040;
-pub static GroupRead: FilePermission = 0x020;
-pub static GroupWrite: FilePermission = 0x010;
-pub static GroupExecute: FilePermission = 0x008;
-pub static OtherRead: FilePermission = 0x004;
-pub static OtherWrite: FilePermission = 0x002;
-pub static OtherExecute: FilePermission = 0x001;
-
-// Common combinations of these bits
-pub static UserRWX: FilePermission = UserRead | UserWrite | UserExecute;
-pub static GroupRWX: FilePermission = GroupRead | GroupWrite | GroupExecute;
-pub static OtherRWX: FilePermission = OtherRead | OtherWrite | OtherExecute;
-
-/// A set of permissions for user owned files, this is equivalent to 0644 on
-/// unix-like systems.
-pub static UserFile: FilePermission = UserRead | UserWrite | GroupRead | OtherRead;
-/// A set of permissions for user owned directories, this is equivalent to 0755
-/// on unix-like systems.
-pub static UserDir: FilePermission = UserRWX | GroupRead | GroupExecute |
- OtherRead | OtherExecute;
-/// A set of permissions for user owned executables, this is equivalent to 0755
-/// on unix-like systems.
-pub static UserExec: FilePermission = UserDir;
-
-/// A mask for all possible permission bits
-pub static AllPermissions: FilePermission = 0x1ff;
+bitflags!(
+ #[doc="A set of permissions for a file or directory is represented
+by a set of flags which are or'd together."]
+ #[deriving(Hash)]
+ #[deriving(Show)]
+ flags FilePermission: u32 {
+ static UserRead = 0o400,
+ static UserWrite = 0o200,
+ static UserExecute = 0o100,
+ static GroupRead = 0o040,
+ static GroupWrite = 0o020,
+ static GroupExecute = 0o010,
+ static OtherRead = 0o004,
+ static OtherWrite = 0o002,
+ static OtherExecute = 0o001,
+
+ static UserRWX = UserRead.bits | UserWrite.bits | UserExecute.bits,
+ static GroupRWX = GroupRead.bits | GroupWrite.bits | GroupExecute.bits,
+ static OtherRWX = OtherRead.bits | OtherWrite.bits | OtherExecute.bits,
+
+ #[doc="Permissions for user owned files, equivalent to 0644 on
+unix-like systems."]
+ static UserFile = UserRead.bits | UserWrite.bits | GroupRead.bits | OtherRead.bits,
+
+ #[doc="Permissions for user owned directories, equivalent to 0755 on
+unix-like systems."]
+ static UserDir = UserRWX.bits | GroupRead.bits | GroupExecute.bits |
+ OtherRead.bits | OtherExecute.bits,
+
+ #[doc="Permissions for user owned executables, equivalent to 0755
+on unix-like systems."]
+ static UserExec = UserDir.bits,
+
+ #[doc="All possible permissions enabled."]
+ static AllPermissions = UserRWX.bits | GroupRWX.bits | OtherRWX.bits
+ }
+)
use io::{Reader, Writer, Listener, Acceptor};
use kinds::Send;
use option::{None, Some, Option};
+use owned::Box;
use rt::rtio::{IoFactory, LocalIo, RtioSocket, RtioTcpListener};
use rt::rtio::{RtioTcpAcceptor, RtioTcpStream};
/// drop(stream); // close the connection
/// ```
pub struct TcpStream {
- obj: ~RtioTcpStream:Send
+ obj: Box<RtioTcpStream:Send>,
}
impl TcpStream {
- fn new(s: ~RtioTcpStream:Send) -> TcpStream {
+ fn new(s: Box<RtioTcpStream:Send>) -> TcpStream {
TcpStream { obj: s }
}
pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
self.obj.socket_name()
}
+
+ /// Sets the nodelay flag on this connection to the boolean specified
+ #[experimental]
+ pub fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> {
+ if nodelay {
+ self.obj.nodelay()
+ } else {
+ self.obj.control_congestion()
+ }
+ }
+
+ /// Sets the keepalive timeout to the timeout specified.
+ ///
+ /// If the value specified is `None`, then the keepalive flag is cleared on
+ /// this connection. Otherwise, the keepalive timeout will be set to the
+ /// specified time, in seconds.
+ #[experimental]
+ pub fn set_keepalive(&mut self, delay_in_seconds: Option<uint>) -> IoResult<()> {
+ match delay_in_seconds {
+ Some(i) => self.obj.keepalive(i),
+ None => self.obj.letdie(),
+ }
+ }
}
impl Clone for TcpStream {
/// # }
/// ```
pub struct TcpListener {
- obj: ~RtioTcpListener:Send
+ obj: Box<RtioTcpListener:Send>,
}
impl TcpListener {
/// a `TcpListener`'s `listen` method, and this object can be used to accept new
/// `TcpStream` instances.
pub struct TcpAcceptor {
- obj: ~RtioTcpAcceptor:Send
+ obj: Box<RtioTcpAcceptor:Send>,
}
impl TcpAcceptor {
//! datagram protocol.
use clone::Clone;
-use io::net::ip::SocketAddr;
+use io::net::ip::{SocketAddr, IpAddr};
use io::{Reader, Writer, IoResult};
use kinds::Send;
+use owned::Box;
use result::{Ok, Err};
use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, LocalIo};
/// drop(socket); // close the socket
/// ```
pub struct UdpSocket {
- obj: ~RtioUdpSocket:Send
+ obj: Box<RtioUdpSocket:Send>,
}
impl UdpSocket {
pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
self.obj.socket_name()
}
+
+ /// Joins a multicast IP address (becomes a member of it)
+ #[experimental]
+ pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
+ self.obj.join_multicast(multi)
+ }
+
+ /// Leaves a multicast IP address (drops membership from it)
+ #[experimental]
+ pub fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
+ self.obj.leave_multicast(multi)
+ }
+
+ /// Set the multicast loop flag to the specified value
+ ///
+ /// This lets multicast packets loop back to local sockets (if enabled)
+ #[experimental]
+ pub fn set_multicast_loop(&mut self, on: bool) -> IoResult<()> {
+ if on {
+ self.obj.loop_multicast_locally()
+ } else {
+ self.obj.dont_loop_multicast_locally()
+ }
+ }
+
+ /// Sets the multicast TTL
+ #[experimental]
+ pub fn set_multicast_ttl(&mut self, ttl: int) -> IoResult<()> {
+ self.obj.multicast_time_to_live(ttl)
+ }
+
+ /// Sets this socket's TTL
+ #[experimental]
+ pub fn set_ttl(&mut self, ttl: int) -> IoResult<()> {
+ self.obj.time_to_live(ttl)
+ }
+
+ /// Sets the broadcast flag on or off
+ #[experimental]
+ pub fn set_broadast(&mut self, broadcast: bool) -> IoResult<()> {
+ if broadcast {
+ self.obj.hear_broadcasts()
+ } else {
+ self.obj.ignore_broadcasts()
+ }
+ }
}
impl Clone for UdpSocket {
use io::pipe::PipeStream;
use io::{Listener, Acceptor, Reader, Writer, IoResult};
use kinds::Send;
+use owned::Box;
use rt::rtio::{IoFactory, LocalIo, RtioUnixListener};
use rt::rtio::{RtioUnixAcceptor, RtioPipe};
}
impl UnixStream {
- fn new(obj: ~RtioPipe:Send) -> UnixStream {
+ fn new(obj: Box<RtioPipe:Send>) -> UnixStream {
UnixStream { obj: PipeStream::new(obj) }
}
/// A value that can listen for incoming named pipe connection requests.
pub struct UnixListener {
/// The internal, opaque runtime Unix listener.
- obj: ~RtioUnixListener:Send,
+ obj: Box<RtioUnixListener:Send>,
}
impl UnixListener {
/// A value that can accept named pipe connections, returned from `listen()`.
pub struct UnixAcceptor {
/// The internal, opaque runtime Unix acceptor.
- obj: ~RtioUnixAcceptor:Send,
+ obj: Box<RtioUnixAcceptor:Send>,
}
impl UnixAcceptor {
use prelude::*;
use io::IoResult;
use libc;
+use owned::Box;
use rt::rtio::{RtioPipe, LocalIo};
/// A synchronous, in-memory pipe.
pub struct PipeStream {
/// The internal, opaque runtime pipe object.
- obj: ~RtioPipe:Send,
+ obj: Box<RtioPipe:Send>,
}
impl PipeStream {
}
#[doc(hidden)]
- pub fn new(inner: ~RtioPipe:Send) -> PipeStream {
+ pub fn new(inner: Box<RtioPipe:Send>) -> PipeStream {
PipeStream { obj: inner }
}
}
use io;
use libc;
use mem;
+use owned::Box;
use rt::rtio::{RtioProcess, IoFactory, LocalIo};
/// Signal a process to exit, without forcibly killing it. Corresponds to
/// assert!(child.wait().success());
/// ```
pub struct Process {
- handle: ~RtioProcess:Send,
+ handle: Box<RtioProcess:Send>,
/// Handle to the child's stdin, if the `stdin` field of this process's
/// `ProcessConfig` was `CreatePipe`. By default, this handle is `Some`.
use kinds::Send;
use mem::drop;
use option::{Some, None};
+use owned::Box;
use result::{Ok, Err};
use rt::rtio::{IoFactory, LocalIo, RtioSignal};
use slice::ImmutableVector;
/// ```
pub struct Listener {
/// A map from signums to handles to keep the handles in memory
- handles: Vec<(Signum, ~RtioSignal:Send)>,
+ handles: Vec<(Signum, Box<RtioSignal:Send>)>,
/// This is where all the handles send signums, which are received by
/// the clients from the receiver.
tx: Sender<Signum>,
use kinds::Send;
use mem::replace;
use option::{Option, Some, None};
+use owned::Box;
use prelude::drop;
use result::{Ok, Err};
use rt;
// tl;dr; TTY works on everything but when windows stdout is redirected, in that
// case pipe also doesn't work, but magically file does!
enum StdSource {
- TTY(~RtioTTY:Send),
- File(~RtioFileStream:Send),
+ TTY(Box<RtioTTY:Send>),
+ File(Box<RtioFileStream:Send>),
}
fn src<T>(fd: libc::c_int, readable: bool, f: |StdSource| -> T) -> T {
src(libc::STDERR_FILENO, false, |src| StdWriter { inner: src })
}
-fn reset_helper(w: ~Writer:Send,
- f: |&mut Task, ~Writer:Send| -> Option<~Writer:Send>)
- -> Option<~Writer:Send>
-{
+fn reset_helper(w: Box<Writer:Send>,
+ f: |&mut Task, Box<Writer:Send>| -> Option<Box<Writer:Send>>)
+ -> Option<Box<Writer:Send>> {
let mut t = Local::borrow(None::<Task>);
// Be sure to flush any pending output from the writer
match f(&mut *t, w) {
///
/// Note that this does not need to be called for all new tasks; the default
/// output handle is to the process's stdout stream.
-pub fn set_stdout(stdout: ~Writer:Send) -> Option<~Writer:Send> {
+pub fn set_stdout(stdout: Box<Writer:Send>) -> Option<Box<Writer:Send>> {
reset_helper(stdout, |t, w| replace(&mut t.stdout, Some(w)))
}
///
/// Note that this does not need to be called for all new tasks; the default
/// output handle is to the process's stderr stream.
-pub fn set_stderr(stderr: ~Writer:Send) -> Option<~Writer:Send> {
+pub fn set_stderr(stderr: Box<Writer:Send>) -> Option<Box<Writer:Send>> {
reset_helper(stderr, |t, w| replace(&mut t.stderr, Some(w)))
}
// })
// })
fn with_task_stdout(f: |&mut Writer| -> IoResult<()> ) {
- let task: Option<~Task> = Local::try_take();
+ let task: Option<Box<Task>> = Local::try_take();
let result = match task {
Some(mut task) => {
// Printing may run arbitrary code, so ensure that the task is in
Local::put(task);
if my_stdout.is_none() {
- my_stdout = Some(box stdout() as ~Writer:Send);
+ my_stdout = Some(box stdout() as Box<Writer:Send>);
}
let ret = f(*my_stdout.get_mut_ref());
use comm::Receiver;
use io::IoResult;
use kinds::Send;
+use owned::Box;
use rt::rtio::{IoFactory, LocalIo, RtioTimer};
/// A synchronous timer object
/// # }
/// ```
pub struct Timer {
- obj: ~RtioTimer:Send,
+ obj: Box<RtioTimer:Send>,
}
/// Sleep the current task for `msecs` milliseconds.
use prelude::*;
use cmp;
use io;
+use owned::Box;
use slice::bytes::MutableByteVector;
/// Wraps a `Reader`, limiting the number of bytes that can be read from it.
/// A `Writer` which multiplexes writes to a set of `Writers`.
pub struct MultiWriter {
- writers: Vec<~Writer>
+ writers: Vec<Box<Writer>>
}
impl MultiWriter {
/// Creates a new `MultiWriter`
- pub fn new(writers: Vec<~Writer>) -> MultiWriter {
+ pub fn new(writers: Vec<Box<Writer>>) -> MultiWriter {
MultiWriter { writers: writers }
}
}
mod test {
use io;
use io::{MemReader, MemWriter};
+ use owned::Box;
use super::*;
use prelude::*;
}
}
- let mut multi = MultiWriter::new(vec!(box TestWriter as ~Writer,
- box TestWriter as ~Writer));
+ let mut multi = MultiWriter::new(vec!(box TestWriter as Box<Writer>,
+ box TestWriter as Box<Writer>));
multi.write([1, 2, 3]).unwrap();
assert_eq!(2, unsafe { writes });
assert_eq!(0, unsafe { flushes });
None => { break }
}
}
- ```
+```
This `for` loop syntax can be applied to any iterator over any type.
use prelude::*;
use cmp;
+ use owned::Box;
use uint;
use num;
#[test]
fn test_all() {
- let v: ~&[int] = box &[1, 2, 3, 4, 5];
+ let v: Box<&[int]> = box &[1, 2, 3, 4, 5];
assert!(v.iter().all(|&x| x < 10));
assert!(!v.iter().all(|&x| x % 2 == 0));
assert!(!v.iter().all(|&x| x > 100));
#[test]
fn test_any() {
- let v: ~&[int] = box &[1, 2, 3, 4, 5];
+ let v: Box<&[int]> = box &[1, 2, 3, 4, 5];
assert!(v.iter().any(|&x| x < 10));
assert!(v.iter().any(|&x| x % 2 == 0));
assert!(!v.iter().any(|&x| x > 100));
/// `Share`, and so are simple aggregate types containing them (like
/// tuples, structs and enums). More instances of basic `Share` types
/// include "immutable" types like `&T` and those with simple
-/// inherited mutability, such as `~T`, `Vec<T>` and most other
+/// inherited mutability, such as `Box<T>`, `Vec<T>` and most other
/// collection types. (Generic parameters need to be `Share` for their
/// container to be `Share`.)
///
#[cfg(test)] pub use ops = realstd::ops;
#[cfg(test)] pub use cmp = realstd::cmp;
#[cfg(test)] pub use ty = realstd::ty;
+#[cfg(test)] pub use owned = realstd::owned;
// Run tests with libgreen instead of libnative.
//
pub mod ascii;
pub mod ptr;
-pub mod owned;
mod managed;
mod reference;
pub mod rc;
#[cfg(not(test))] pub mod ops;
#[cfg(not(test))] pub mod cmp;
#[cfg(not(test))] pub mod ty;
+#[cfg(not(test))] pub mod owned;
/* Common traits */
local_data::set(key_vector, ~[4]);
local_data::get(key_vector, |opt| assert_eq!(*opt.unwrap(), ~[4]));
- ```
+```
*/
use kinds::Send;
use mem::replace;
use option::{None, Option, Some};
+use owned::Box;
use rt::task::{Task, LocalStorage};
use slice::{ImmutableVector, MutableVector};
use vec::Vec;
// a proper map.
#[doc(hidden)]
pub type Map = Vec<Option<(*u8, TLSValue, LoanState)>>;
-type TLSValue = ~LocalData:Send;
+type TLSValue = Box<LocalData:Send>;
// Gets the map from the runtime. Lazily initialises if not done so already.
unsafe fn get_local_map() -> &mut Map {
// Move `data` into transmute to get out the memory that it
// owns, we must free it manually later.
- let (_vtable, alloc): (uint, ~T) = unsafe {
+ let (_vtable, alloc): (uint, Box<T>) = unsafe {
cast::transmute(data)
};
want.describe(), cur.describe());
}
}
- // data was created with `~T as ~LocalData`, so we extract
- // pointer part of the trait, (as ~T), and then use
- // compiler coercions to achieve a '&' pointer.
+ // data was created with `box T as Box<LocalData>`, so we
+ // extract pointer part of the trait, (as Box<T>), and
+ // then use compiler coercions to achieve a '&' pointer.
unsafe {
- match *cast::transmute::<&TLSValue, &(uint, ~T)>(data){
+ match *cast::transmute::<&TLSValue,
+ &(uint, Box<T>)>(data){
(_vtable, ref alloc) => {
let value: &T = *alloc;
ret = f(Some(value));
let keyval = key_to_key_value(key);
// When the task-local map is destroyed, all the data needs to be cleaned
- // up. For this reason we can't do some clever tricks to store '~T' as a
- // '*c_void' or something like that. To solve the problem, we cast
+ // up. For this reason we can't do some clever tricks to store 'Box<T>' as
+ // a '*c_void' or something like that. To solve the problem, we cast
// everything to a trait (LocalData) which is then stored inside the map.
// Upon destruction of the map, all the objects will be destroyed and the
// traits have enough information about them to destroy themselves.
- let data = box data as ~LocalData:;
+ let data = box data as Box<LocalData:>;
fn insertion_position(map: &mut Map,
key: *u8) -> Option<uint> {
// transmute here to add the Send bound back on. This doesn't actually
// matter because TLS will always own the data (until its moved out) and
// we're not actually sending it to other schedulers or anything.
- let data: ~LocalData:Send = unsafe { cast::transmute(data) };
+ let data: Box<LocalData:Send> = unsafe { cast::transmute(data) };
match insertion_position(map, keyval) {
Some(i) => { *map.get_mut(i) = Some((keyval, data, NoLoan)); }
None => { map.push(Some((keyval, data, NoLoan))); }
mod tests {
use prelude::*;
use super::*;
+ use owned::Box;
use task;
use str::StrSlice;
#[test]
fn test_owned() {
- static key: Key<~int> = &Key;
+ static key: Key<Box<int>> = &Key;
set(key, box 1);
get(key, |v| {
/// The entry point for failure of rust tasks.
///
/// This macro is used to inject failure into a rust task, causing the task to
-/// unwind and fail entirely. Each task's failure can be reaped as the `~Any`
-/// type, and the single-argument form of the `fail!` macro will be the value
-/// which is transmitted.
+/// unwind and fail entirely. Each task's failure can be reaped as the
+/// `Box<Any>` type, and the single-argument form of the `fail!` macro will be
+/// the value which is transmitted.
///
/// The multi-argument form of this macro fails with a string and has the
/// `format!` syntax for building a string.
//!
//! Rust's pointer types must always point to a valid location; there are
//! no "null" pointers. Instead, Rust has *optional* pointers, like
-//! the optional owned box, `Option<~T>`.
+//! the optional owned box, `Option<Box<T>>`.
//!
//! The following example uses `Option` to create an optional box of
//! `int`. Notice that in order to use the inner `int` value first the
//! not (`None`).
//!
//! ```
-//! let optional: Option<~int> = None;
+//! let optional: Option<Box<int>> = None;
//! check_optional(&optional);
//!
-//! let optional: Option<~int> = Some(~9000);
+//! let optional: Option<Box<int>> = Some(box 9000);
//! check_optional(&optional);
//!
-//! fn check_optional(optional: &Option<~int>) {
+//! fn check_optional(optional: &Option<Box<int>>) {
//! match *optional {
//! Some(ref p) => println!("have value {}", p),
//! None => println!("have no value")
//!
//! This usage of `Option` to create safe nullable pointers is so
//! common that Rust does special optimizations to make the
-//! representation of `Option<~T>` a single pointer. Optional pointers
+//! representation of `Option<Box<T>>` a single pointer. Optional pointers
//! in Rust are stored as efficiently as any other pointer type.
//!
//! # Examples
pub struct Box<T>(*T);
#[cfg(not(test))]
-impl<T:Eq> Eq for ~T {
+impl<T:Eq> Eq for Box<T> {
#[inline]
- fn eq(&self, other: &~T) -> bool { *(*self) == *(*other) }
+ fn eq(&self, other: &Box<T>) -> bool { *(*self) == *(*other) }
#[inline]
- fn ne(&self, other: &~T) -> bool { *(*self) != *(*other) }
+ fn ne(&self, other: &Box<T>) -> bool { *(*self) != *(*other) }
}
#[cfg(not(test))]
-impl<T:Ord> Ord for ~T {
+impl<T:Ord> Ord for Box<T> {
#[inline]
- fn lt(&self, other: &~T) -> bool { *(*self) < *(*other) }
+ fn lt(&self, other: &Box<T>) -> bool { *(*self) < *(*other) }
#[inline]
- fn le(&self, other: &~T) -> bool { *(*self) <= *(*other) }
+ fn le(&self, other: &Box<T>) -> bool { *(*self) <= *(*other) }
#[inline]
- fn ge(&self, other: &~T) -> bool { *(*self) >= *(*other) }
+ fn ge(&self, other: &Box<T>) -> bool { *(*self) >= *(*other) }
#[inline]
- fn gt(&self, other: &~T) -> bool { *(*self) > *(*other) }
+ fn gt(&self, other: &Box<T>) -> bool { *(*self) > *(*other) }
}
#[cfg(not(test))]
-impl<T: TotalOrd> TotalOrd for ~T {
+impl<T: TotalOrd> TotalOrd for Box<T> {
#[inline]
- fn cmp(&self, other: &~T) -> Ordering { (**self).cmp(*other) }
+ fn cmp(&self, other: &Box<T>) -> Ordering { (**self).cmp(*other) }
}
#[cfg(not(test))]
-impl<T: TotalEq> TotalEq for ~T {}
+impl<T: TotalEq> TotalEq for Box<T> {}
pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
pub use num::{Signed, Unsigned};
pub use num::{Primitive, Int, Float, ToPrimitive, FromPrimitive};
+pub use owned::Box;
pub use path::{GenericPath, Path, PosixPath, WindowsPath};
pub use ptr::RawPtr;
pub use io::{Buffer, Writer, Reader, Seek};
//! and requires no resource management later,
//! but you must not use the pointer after its lifetime.
//!
-//! ## 2. Transmute an owned box (`~T`).
+//! ## 2. Transmute an owned box (`Box<T>`).
//!
//! The `transmute` function takes, by value, whatever it's given
//! and returns it as whatever type is requested, as long as the
-//! types are the same size. Because `~T` and `*T` have the same
+//! types are the same size. Because `Box<T>` and `*T` have the same
//! representation they can be trivially,
//! though unsafely, transformed from one type to the other.
//!
//! use std::cast;
//!
//! unsafe {
-//! let my_num: ~int = ~10;
+//! let my_num: Box<int> = box 10;
//! let my_num: *int = cast::transmute(my_num);
-//! let my_speed: ~int = ~88;
+//! let my_speed: Box<int> = box 88;
//! let my_speed: *mut int = cast::transmute(my_speed);
//!
-//! // By taking ownership of the original `~T` though
+//! // By taking ownership of the original `Box<T>` though
//! // we are obligated to transmute it back later to be destroyed.
-//! drop(cast::transmute::<_, ~int>(my_speed));
-//! drop(cast::transmute::<_, ~int>(my_num));
+//! drop(cast::transmute::<_, Box<int>>(my_speed));
+//! drop(cast::transmute::<_, Box<int>>(my_num));
//! }
//! ```
//!
use intrinsics::{Disr, Opaque, TyDesc, TyVisitor};
use mem;
+use owned::Box;
/**
* Trait for visitor that wishes to reflect on data. To use this, create a
}
fn visit_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
- self.align_to::<~u8>();
+ self.align_to::<Box<u8>>();
if ! self.inner.visit_uniq(mtbl, inner) { return false; }
- self.bump_past::<~u8>();
+ self.bump_past::<Box<u8>>();
true
}
}
fn visit_trait(&mut self, name: &str) -> bool {
- self.align_to::<~TyVisitor>();
+ self.align_to::<Box<TyVisitor>>();
if ! self.inner.visit_trait(name) { return false; }
- self.bump_past::<~TyVisitor>();
+ self.bump_past::<Box<TyVisitor>>();
true
}
}
fn visit_uniq(&mut self, _mtbl: uint, inner: *TyDesc) -> bool {
- try!(self, self.writer.write(['~' as u8]));
+ try!(self, self.writer.write("box ".as_bytes()));
self.get::<*u8>(|this, b| {
this.visit_ptr_inner(*b, inner)
})
fn visit_evec_uniq(&mut self, mtbl: uint, inner: *TyDesc) -> bool {
self.get::<&raw::Vec<()>>(|this, b| {
- try!(this, this.writer.write(['~' as u8]));
+ try!(this, this.writer.write("box ".as_bytes()));
this.write_unboxed_vec_repr(mtbl, *b, inner)
})
}
use io::stdio::println;
use char::is_alphabetic;
use mem::swap;
+ use owned::Box;
fn exact_test<T>(t: &T, e:&str) {
let mut m = io::MemWriter::new();
exact_test(&("he\u10f3llo".to_owned()), "~\"he\\u10f3llo\"");
exact_test(&(@10), "@10");
- exact_test(&(box 10), "~10");
+ exact_test(&(box 10), "box 10");
exact_test(&(&10), "&10");
let mut x = 10;
exact_test(&(&mut x), "&mut 10");
exact_test(&(0 as *mut ()), "(0x0 as *mut ())");
exact_test(&(1,), "(1,)");
- exact_test(&(box ["hi", "there"]),
- "~[\"hi\", \"there\"]");
exact_test(&(&["hi", "there"]),
"&[\"hi\", \"there\"]");
exact_test(&(P{a:10, b:1.234}),
exact_test(&(@P{a:10, b:1.234}),
"@repr::P{a: 10, b: 1.234f64}");
exact_test(&(box P{a:10, b:1.234}),
- "~repr::P{a: 10, b: 1.234f64}");
+ "box repr::P{a: 10, b: 1.234f64}");
exact_test(&(10u8, "hello".to_owned()),
"(10u8, ~\"hello\")");
exact_test(&(10u16, "hello".to_owned()),
exact_test(&println, "fn(&str)");
exact_test(&swap::<int>, "fn(&mut int, &mut int)");
exact_test(&is_alphabetic, "fn(char) -> bool");
- exact_test(&(box 5 as ~ToStr), "~to_str::ToStr<no-bounds>");
-
- struct Foo;
- exact_test(&(box [Foo, Foo]), "~[repr::test_repr::Foo, repr::test_repr::Foo]");
struct Bar(int, int);
exact_test(&(Bar(2, 2)), "repr::test_repr::Bar(2, 2)");
use clone::Clone;
use option::{Option, Some, None};
use iter::Iterator;
+ use owned::Box;
use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
use mem;
#[cfg(not(test))] use str::StrSlice;
with_lock(|| unsafe {
let ptr = get_global_ptr();
let val = mem::replace(&mut *ptr, None);
- val.as_ref().map(|s: &~~[~[u8]]| (**s).clone())
+ val.as_ref().map(|s: &Box<~[~[u8]]>| (**s).clone())
})
}
pub fn clone() -> Option<~[~[u8]]> {
with_lock(|| unsafe {
let ptr = get_global_ptr();
- (*ptr).as_ref().map(|s: &~~[~[u8]]| (**s).clone())
+ (*ptr).as_ref().map(|s: &Box<~[~[u8]]>| (**s).clone())
})
}
}
}
- fn get_global_ptr() -> *mut Option<~~[~[u8]]> {
+ fn get_global_ptr() -> *mut Option<Box<~[~[u8]]>> {
unsafe { cast::transmute(&global_args_ptr) }
}
use kinds::Send;
use mem;
use option::{Some, None};
+use owned::Box;
use ptr::RawPtr;
use unstable::sync::Exclusive;
use slice::OwnedVector;
unsafe {
rtassert!(!RUNNING);
rtassert!(QUEUE.is_null());
- let state: ~Queue = box Exclusive::new(vec!());
+ let state: Box<Queue> = box Exclusive::new(vec!());
QUEUE = cast::transmute(state);
}
}
rtassert!(!RUNNING);
rtassert!(!QUEUE.is_null());
RUNNING = true;
- let state: ~Queue = cast::transmute(QUEUE);
+ let state: Box<Queue> = cast::transmute(QUEUE);
QUEUE = 0 as *mut Queue;
let mut vec = None;
state.with(|arr| {
// see src/librustc/back/link.rs for these mappings
demangle! (
"$SP$" => "@",
- "$UP$" => "~",
+ "$UP$" => "Box",
"$RP$" => "*",
"$BP$" => "&",
"$LT$" => "<",
#[test]
fn demangle_dollars() {
- t!("_ZN4$UP$E", "~");
- t!("_ZN8$UP$testE", "~test");
- t!("_ZN8$UP$test4foobE", "~test::foob");
+ t!("_ZN4$UP$E", "Box");
+ t!("_ZN8$UP$testE", "Boxtest");
+ t!("_ZN8$UP$test4foobE", "Boxtest::foob");
t!("_ZN8$x20test4foobE", " test::foob");
}
#[test]
fn demangle_many_dollars() {
t!("_ZN12test$x20test4foobE", "test test::foob");
- t!("_ZN12test$UP$test4foobE", "test~test::foob");
+ t!("_ZN12test$UP$test4foobE", "testBoxtest::foob");
}
}
#[lang="exchange_malloc"]
#[inline]
pub unsafe fn exchange_malloc(size: uint) -> *mut u8 {
- // The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
- // allocations can point to this `static`. It would be incorrect to use a null
- // pointer, due to enums assuming types like unique pointers are never null.
+ // The compiler never calls `exchange_free` on Box<ZeroSizeType>, so
+ // zero-size allocations can point to this `static`. It would be incorrect
+ // to use a null pointer, due to enums assuming types like unique pointers
+ // are never null.
static EMPTY: () = ();
if size == 0 {
// except according to those terms.
use option::Option;
+use owned::Box;
use rt::task::Task;
use rt::local_ptr;
/// Encapsulates some task-local data.
pub trait Local<Borrowed> {
- fn put(value: ~Self);
- fn take() -> ~Self;
- fn try_take() -> Option<~Self>;
+ fn put(value: Box<Self>);
+ fn take() -> Box<Self>;
+ fn try_take() -> Option<Box<Self>>;
fn exists(unused_value: Option<Self>) -> bool;
fn borrow(unused_value: Option<Self>) -> Borrowed;
- unsafe fn unsafe_take() -> ~Self;
+ unsafe fn unsafe_take() -> Box<Self>;
unsafe fn unsafe_borrow() -> *mut Self;
unsafe fn try_unsafe_borrow() -> Option<*mut Self>;
}
#[allow(visible_private_types)]
impl Local<local_ptr::Borrowed<Task>> for Task {
#[inline]
- fn put(value: ~Task) { unsafe { local_ptr::put(value) } }
+ fn put(value: Box<Task>) { unsafe { local_ptr::put(value) } }
#[inline]
- fn take() -> ~Task { unsafe { local_ptr::take() } }
+ fn take() -> Box<Task> { unsafe { local_ptr::take() } }
#[inline]
- fn try_take() -> Option<~Task> { unsafe { local_ptr::try_take() } }
+ fn try_take() -> Option<Box<Task>> { unsafe { local_ptr::try_take() } }
fn exists(_: Option<Task>) -> bool { local_ptr::exists() }
#[inline]
fn borrow(_: Option<Task>) -> local_ptr::Borrowed<Task> {
}
}
#[inline]
- unsafe fn unsafe_take() -> ~Task { local_ptr::unsafe_take() }
+ unsafe fn unsafe_take() -> Box<Task> { local_ptr::unsafe_take() }
#[inline]
unsafe fn unsafe_borrow() -> *mut Task { local_ptr::unsafe_borrow() }
#[inline]
use option::{None, Option};
use unstable::run_in_bare_thread;
use super::*;
+ use owned::Box;
use rt::task::Task;
#[test]
run_in_bare_thread(proc() {
let task = box Task::new();
Local::put(task);
- let task: ~Task = Local::take();
+ let task: Box<Task> = Local::take();
cleanup_task(task);
});
}
run_in_bare_thread(proc() {
let task = box Task::new();
Local::put(task);
- let task: ~Task = Local::take();
+ let task: Box<Task> = Local::take();
cleanup_task(task);
let task = box Task::new();
Local::put(task);
- let task: ~Task = Local::take();
+ let task: Box<Task> = Local::take();
cleanup_task(task);
});
}
unsafe {
let _task: *mut Task = Local::unsafe_borrow();
}
- let task: ~Task = Local::take();
+ let task: Box<Task> = Local::take();
cleanup_task(task);
});
}
let _ = Local::borrow(None::<Task>);
}
- let task: ~Task = Local::take();
+ let task: Box<Task> = Local::take();
cleanup_task(task);
});
}
let task = box Task::new();
Local::put(task);
- let t: ~Task = Local::try_take().unwrap();
- let u: Option<~Task> = Local::try_take();
+ let t: Box<Task> = Local::try_take().unwrap();
+ let u: Option<Box<Task>> = Local::try_take();
assert!(u.is_none());
cleanup_task(t);
});
}
- fn cleanup_task(mut t: ~Task) {
+ fn cleanup_task(mut t: Box<Task>) {
t.destroyed = true;
}
//! Access to a single thread-local pointer.
//!
-//! The runtime will use this for storing ~Task.
+//! The runtime will use this for storing Box<Task>.
//!
//! FIXME: Add runtime checks for usage of inconsistent pointer types.
//! and for overwriting an existing pointer.
use cast;
use ops::{Drop, Deref, DerefMut};
+use owned::Box;
use ptr::RawPtr;
#[cfg(windows)] // mingw-w32 doesn't like thread_local things
if self.val.is_null() {
rtabort!("Aiee, returning null borrowed object!");
}
- let val: ~T = cast::transmute(self.val);
+ let val: Box<T> = cast::transmute(self.val);
put::<T>(val);
rtassert!(exists());
}
pub mod compiled {
use cast;
use option::{Option, Some, None};
+ use owned::Box;
use ptr::RawPtr;
#[cfg(test)]
///
/// Does not validate the pointer type.
#[inline(never)] // see comments above
- pub unsafe fn put<T>(sched: ~T) {
+ pub unsafe fn put<T>(sched: Box<T>) {
RT_TLS_PTR = cast::transmute(sched)
}
///
/// Does not validate the pointer type.
#[inline(never)] // see comments above
- pub unsafe fn take<T>() -> ~T {
+ pub unsafe fn take<T>() -> Box<T> {
let ptr = RT_TLS_PTR;
rtassert!(!ptr.is_null());
- let ptr: ~T = cast::transmute(ptr);
+ let ptr: Box<T> = cast::transmute(ptr);
// can't use `as`, due to type not matching with `cfg(test)`
RT_TLS_PTR = cast::transmute(0);
ptr
///
/// Does not validate the pointer type.
#[inline(never)] // see comments above
- pub unsafe fn try_take<T>() -> Option<~T> {
+ pub unsafe fn try_take<T>() -> Option<Box<T>> {
let ptr = RT_TLS_PTR;
if ptr.is_null() {
None
} else {
- let ptr: ~T = cast::transmute(ptr);
+ let ptr: Box<T> = cast::transmute(ptr);
// can't use `as`, due to type not matching with `cfg(test)`
RT_TLS_PTR = cast::transmute(0);
Some(ptr)
/// Does not validate the pointer type.
/// Leaves the old pointer in TLS for speed.
#[inline(never)] // see comments above
- pub unsafe fn unsafe_take<T>() -> ~T {
+ pub unsafe fn unsafe_take<T>() -> Box<T> {
cast::transmute(RT_TLS_PTR)
}
pub mod native {
use cast;
use option::{Option, Some, None};
+ use owned::Box;
use ptr;
use ptr::RawPtr;
use tls = rt::thread_local_storage;
///
/// Does not validate the pointer type.
#[inline]
- pub unsafe fn put<T>(sched: ~T) {
+ pub unsafe fn put<T>(sched: Box<T>) {
let key = tls_key();
let void_ptr: *mut u8 = cast::transmute(sched);
tls::set(key, void_ptr);
///
/// Does not validate the pointer type.
#[inline]
- pub unsafe fn take<T>() -> ~T {
+ pub unsafe fn take<T>() -> Box<T> {
let key = tls_key();
let void_ptr: *mut u8 = tls::get(key);
if void_ptr.is_null() {
rtabort!("thread-local pointer is null. bogus!");
}
- let ptr: ~T = cast::transmute(void_ptr);
+ let ptr: Box<T> = cast::transmute(void_ptr);
tls::set(key, ptr::mut_null());
return ptr;
}
///
/// Does not validate the pointer type.
#[inline]
- pub unsafe fn try_take<T>() -> Option<~T> {
+ pub unsafe fn try_take<T>() -> Option<Box<T>> {
match maybe_tls_key() {
Some(key) => {
let void_ptr: *mut u8 = tls::get(key);
if void_ptr.is_null() {
None
} else {
- let ptr: ~T = cast::transmute(void_ptr);
+ let ptr: Box<T> = cast::transmute(void_ptr);
tls::set(key, ptr::mut_null());
Some(ptr)
}
/// Does not validate the pointer type.
/// Leaves the old pointer in TLS for speed.
#[inline]
- pub unsafe fn unsafe_take<T>() -> ~T {
+ pub unsafe fn unsafe_take<T>() -> Box<T> {
let key = tls_key();
let void_ptr: *mut u8 = tls::get(key);
if void_ptr.is_null() {
rtabort!("thread-local pointer is null. bogus!");
}
- let ptr: ~T = cast::transmute(void_ptr);
+ let ptr: Box<T> = cast::transmute(void_ptr);
return ptr;
}
use any::Any;
use kinds::Send;
use option::Option;
+use owned::Box;
use result::Result;
use task::TaskOpts;
pub trait Runtime {
// Necessary scheduling functions, used for channels and blocking I/O
// (sometimes).
- fn yield_now(~self, cur_task: ~Task);
- fn maybe_yield(~self, cur_task: ~Task);
- fn deschedule(~self, times: uint, cur_task: ~Task,
+ fn yield_now(~self, cur_task: Box<Task>);
+ fn maybe_yield(~self, cur_task: Box<Task>);
+ fn deschedule(~self, times: uint, cur_task: Box<Task>,
f: |BlockedTask| -> Result<(), BlockedTask>);
- fn reawaken(~self, to_wake: ~Task);
+ fn reawaken(~self, to_wake: Box<Task>);
// Miscellaneous calls which are very different depending on what context
// you're in.
- fn spawn_sibling(~self, cur_task: ~Task, opts: TaskOpts, f: proc():Send);
+ fn spawn_sibling(~self,
+ cur_task: Box<Task>,
+ opts: TaskOpts,
+ f: proc():Send);
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>>;
/// The (low, high) edges of the current stack.
fn stack_bounds(&self) -> (uint, uint); // (lo, hi)
fn can_block(&self) -> bool;
// FIXME: This is a serious code smell and this should not exist at all.
- fn wrap(~self) -> ~Any;
+ fn wrap(~self) -> Box<Any>;
}
/// One-time runtime initialization.
use kinds::Send;
use ops::Drop;
use option::{Option, Some, None};
+use owned::Box;
use path::Path;
use result::Err;
use rt::local::Local;
pub trait EventLoop {
fn run(&mut self);
fn callback(&mut self, arg: proc():Send);
- fn pausable_idle_callback(&mut self,
- ~Callback:Send) -> ~PausableIdleCallback:Send;
- fn remote_callback(&mut self, ~Callback:Send) -> ~RemoteCallback:Send;
+ fn pausable_idle_callback(&mut self, Box<Callback:Send>)
+ -> Box<PausableIdleCallback:Send>;
+ fn remote_callback(&mut self, Box<Callback:Send>)
+ -> Box<RemoteCallback:Send>;
/// The asynchronous I/O services. Not all event loops may provide one.
fn io<'a>(&'a mut self) -> Option<&'a mut IoFactory>;
//
// In order to get around this, we just transmute a copy out of the task
// in order to have what is likely a static lifetime (bad).
- let mut t: ~Task = Local::take();
+ let mut t: Box<Task> = Local::take();
let ret = t.local_io().map(|t| {
unsafe { cast::transmute_copy(&t) }
});
pub trait IoFactory {
// networking
fn tcp_connect(&mut self, addr: SocketAddr,
- timeout: Option<u64>) -> IoResult<~RtioTcpStream:Send>;
- fn tcp_bind(&mut self, addr: SocketAddr) -> IoResult<~RtioTcpListener:Send>;
- fn udp_bind(&mut self, addr: SocketAddr) -> IoResult<~RtioUdpSocket:Send>;
+ timeout: Option<u64>) -> IoResult<Box<RtioTcpStream:Send>>;
+ fn tcp_bind(&mut self, addr: SocketAddr)
+ -> IoResult<Box<RtioTcpListener:Send>>;
+ fn udp_bind(&mut self, addr: SocketAddr)
+ -> IoResult<Box<RtioUdpSocket:Send>>;
fn unix_bind(&mut self, path: &CString)
- -> IoResult<~RtioUnixListener:Send>;
+ -> IoResult<Box<RtioUnixListener:Send>>;
fn unix_connect(&mut self, path: &CString,
- timeout: Option<u64>) -> IoResult<~RtioPipe:Send>;
+ timeout: Option<u64>) -> IoResult<Box<RtioPipe:Send>>;
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
hint: Option<ai::Hint>) -> IoResult<~[ai::Info]>;
// filesystem operations
fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior)
- -> ~RtioFileStream:Send;
+ -> Box<RtioFileStream:Send>;
fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
- -> IoResult<~RtioFileStream:Send>;
+ -> IoResult<Box<RtioFileStream:Send>>;
fn fs_unlink(&mut self, path: &CString) -> IoResult<()>;
fn fs_stat(&mut self, path: &CString) -> IoResult<FileStat>;
fn fs_mkdir(&mut self, path: &CString,
IoResult<()>;
// misc
- fn timer_init(&mut self) -> IoResult<~RtioTimer:Send>;
+ fn timer_init(&mut self) -> IoResult<Box<RtioTimer:Send>>;
fn spawn(&mut self, config: ProcessConfig)
- -> IoResult<(~RtioProcess:Send, ~[Option<~RtioPipe:Send>])>;
+ -> IoResult<(Box<RtioProcess:Send>,
+ ~[Option<Box<RtioPipe:Send>>])>;
fn kill(&mut self, pid: libc::pid_t, signal: int) -> IoResult<()>;
- fn pipe_open(&mut self, fd: c_int) -> IoResult<~RtioPipe:Send>;
+ fn pipe_open(&mut self, fd: c_int) -> IoResult<Box<RtioPipe:Send>>;
fn tty_open(&mut self, fd: c_int, readable: bool)
- -> IoResult<~RtioTTY:Send>;
+ -> IoResult<Box<RtioTTY:Send>>;
fn signal(&mut self, signal: Signum, channel: Sender<Signum>)
- -> IoResult<~RtioSignal:Send>;
+ -> IoResult<Box<RtioSignal:Send>>;
}
pub trait RtioTcpListener : RtioSocket {
- fn listen(~self) -> IoResult<~RtioTcpAcceptor:Send>;
+ fn listen(~self) -> IoResult<Box<RtioTcpAcceptor:Send>>;
}
pub trait RtioTcpAcceptor : RtioSocket {
- fn accept(&mut self) -> IoResult<~RtioTcpStream:Send>;
+ fn accept(&mut self) -> IoResult<Box<RtioTcpStream:Send>>;
fn accept_simultaneously(&mut self) -> IoResult<()>;
fn dont_accept_simultaneously(&mut self) -> IoResult<()>;
fn set_timeout(&mut self, timeout: Option<u64>);
fn nodelay(&mut self) -> IoResult<()>;
fn keepalive(&mut self, delay_in_seconds: uint) -> IoResult<()>;
fn letdie(&mut self) -> IoResult<()>;
- fn clone(&self) -> ~RtioTcpStream:Send;
+ fn clone(&self) -> Box<RtioTcpStream:Send>;
fn close_write(&mut self) -> IoResult<()>;
}
fn hear_broadcasts(&mut self) -> IoResult<()>;
fn ignore_broadcasts(&mut self) -> IoResult<()>;
- fn clone(&self) -> ~RtioUdpSocket:Send;
+ fn clone(&self) -> Box<RtioUdpSocket:Send>;
}
pub trait RtioTimer {
pub trait RtioPipe {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint>;
fn write(&mut self, buf: &[u8]) -> IoResult<()>;
- fn clone(&self) -> ~RtioPipe:Send;
+ fn clone(&self) -> Box<RtioPipe:Send>;
}
pub trait RtioUnixListener {
- fn listen(~self) -> IoResult<~RtioUnixAcceptor:Send>;
+ fn listen(~self) -> IoResult<Box<RtioUnixAcceptor:Send>>;
}
pub trait RtioUnixAcceptor {
- fn accept(&mut self) -> IoResult<~RtioPipe:Send>;
+ fn accept(&mut self) -> IoResult<Box<RtioPipe:Send>>;
fn set_timeout(&mut self, timeout: Option<u64>);
}
#[cfg(not(test))] // in testing, use the original libstd's version
pub extern "C" fn rust_stack_exhausted() {
use option::{Option, None, Some};
+ use owned::Box;
use rt::local::Local;
use rt::task::Task;
use str::Str;
// #9854 - unwinding on windows through __morestack has never worked
// #2361 - possible implementation of not using landing pads
- let task: Option<~Task> = Local::try_take();
+ let task: Option<Box<Task>> = Local::try_take();
let name = match task {
Some(ref task) => {
task.name.as_ref().map(|n| n.as_slice())
use local_data;
use ops::Drop;
use option::{Option, Some, None};
+use owned::Box;
use prelude::drop;
use result::{Result, Ok, Err};
use rt::Runtime;
pub destroyed: bool,
pub name: Option<SendStr>,
- pub stdout: Option<~Writer:Send>,
- pub stderr: Option<~Writer:Send>,
+ pub stdout: Option<Box<Writer:Send>>,
+ pub stderr: Option<Box<Writer:Send>>,
- imp: Option<~Runtime:Send>,
+ imp: Option<Box<Runtime:Send>>,
}
pub struct GarbageCollector;
pub struct LocalStorage(pub Option<local_data::Map>);
-/// A handle to a blocked task. Usually this means having the ~Task pointer by
-/// ownership, but if the task is killable, a killer can steal it at any time.
+/// A handle to a blocked task. Usually this means having the Box<Task>
+/// pointer by ownership, but if the task is killable, a killer can steal it
+/// at any time.
pub enum BlockedTask {
- Owned(~Task),
+ Owned(Box<Task>),
Shared(UnsafeArc<AtomicUint>),
}
/// This function is *not* meant to be abused as a "try/catch" block. This
/// is meant to be used at the absolute boundaries of a task's lifetime, and
/// only for that purpose.
- pub fn run(~self, mut f: ||) -> ~Task {
+ pub fn run(~self, mut f: ||) -> Box<Task> {
// Need to put ourselves into TLS, but also need access to the unwinder.
// Unsafely get a handle to the task so we can continue to use it after
// putting it in tls (so we can invoke the unwinder).
let handle: *mut Task = unsafe {
- *cast::transmute::<&~Task, &*mut Task>(&self)
+ *cast::transmute::<&Box<Task>, &*mut Task>(&self)
};
Local::put(self);
let me: *mut Task = Local::unsafe_borrow();
(*me).death.collect_failure((*me).unwinder.result());
}
- let mut me: ~Task = Local::take();
+ let mut me: Box<Task> = Local::take();
me.destroyed = true;
return me;
}
/// Inserts a runtime object into this task, transferring ownership to the
/// task. It is illegal to replace a previous runtime object in this task
/// with this argument.
- pub fn put_runtime(&mut self, ops: ~Runtime:Send) {
+ pub fn put_runtime(&mut self, ops: Box<Runtime:Send>) {
assert!(self.imp.is_none());
self.imp = Some(ops);
}
///
/// It is recommended to only use this method when *absolutely necessary*.
/// This function may not be available in the future.
- pub fn maybe_take_runtime<T: 'static>(&mut self) -> Option<~T> {
+ pub fn maybe_take_runtime<T: 'static>(&mut self) -> Option<Box<T>> {
// This is a terrible, terrible function. The general idea here is to
- // take the runtime, cast it to ~Any, check if it has the right type,
- // and then re-cast it back if necessary. The method of doing this is
- // pretty sketchy and involves shuffling vtables of trait objects
- // around, but it gets the job done.
+ // take the runtime, cast it to Box<Any>, check if it has the right
+ // type, and then re-cast it back if necessary. The method of doing
+ // this is pretty sketchy and involves shuffling vtables of trait
+ // objects around, but it gets the job done.
//
// FIXME: This function is a serious code smell and should be avoided at
// all costs. I have yet to think of a method to avoid this
Ok(t) => Some(t),
Err(t) => {
let (_, obj): (uint, uint) = cast::transmute(t);
- let obj: ~Runtime:Send = cast::transmute((vtable, obj));
+ let obj: Box<Runtime:Send> =
+ cast::transmute((vtable, obj));
self.put_runtime(obj);
None
}
impl BlockedTask {
/// Returns Some if the task was successfully woken; None if already killed.
- pub fn wake(self) -> Option<~Task> {
+ pub fn wake(self) -> Option<Box<Task>> {
match self {
Owned(task) => Some(task),
Shared(arc) => unsafe {
#[cfg(test)] pub fn trash(self) { assert!(self.wake().is_none()); }
/// Create a blocked task, unless the task was already killed.
- pub fn block(task: ~Task) -> BlockedTask {
+ pub fn block(task: Box<Task>) -> BlockedTask {
Owned(task)
}
if blocked_task_ptr & 0x1 == 0 {
Owned(cast::transmute(blocked_task_ptr))
} else {
- let ptr: ~UnsafeArc<AtomicUint> =
+ let ptr: Box<UnsafeArc<AtomicUint>> =
cast::transmute(blocked_task_ptr & !1);
Shared(*ptr)
}
use libc;
use ops::Drop;
use option::{Option, Some, None};
+use owned::Box;
use uint;
type StartFn = extern "C" fn(*libc::c_void) -> imp::rust_thread_return;
pub struct Thread<T> {
native: imp::rust_thread,
joined: bool,
- packet: ~Option<T>,
+ packet: Box<Option<T>>,
}
static DEFAULT_STACK_SIZE: uint = 1024 * 1024;
use rt::stack;
unsafe {
stack::record_stack_bounds(0, uint::MAX);
- let f: ~proc() = cast::transmute(main);
+ let f: Box<proc()> = cast::transmute(main);
(*f)();
cast::transmute(0 as imp::rust_thread_return)
}
pub fn start_stack<T: Send>(stack: uint, main: proc():Send -> T) -> Thread<T> {
// We need the address of the packet to fill in to be stable so when
- // `main` fills it in it's still valid, so allocate an extra ~ box to do
+ // `main` fills it in it's still valid, so allocate an extra box to do
// so.
let packet = box None;
let packet2: *mut Option<T> = unsafe {
- *cast::transmute::<&~Option<T>, **mut Option<T>>(&packet)
+ *cast::transmute::<&Box<Option<T>>, **mut Option<T>>(&packet)
};
let main = proc() unsafe { *packet2 = Some(main()); };
let native = unsafe { imp::create(stack, box main) };
use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T, BOOL,
LPVOID, DWORD, LPDWORD, HANDLE};
use os;
+ use owned::Box;
use ptr;
use rt::stack::RED_ZONE;
pub type rust_thread = HANDLE;
pub type rust_thread_return = DWORD;
- pub unsafe fn create(stack: uint, p: ~proc():Send) -> rust_thread {
+ pub unsafe fn create(stack: uint, p: Box<proc():Send>) -> rust_thread {
let arg: *mut libc::c_void = cast::transmute(p);
// FIXME On UNIX, we guard against stack sizes that are too small but
// that's because pthreads enforces that stacks are at least
if ret as uint == 0 {
// be sure to not leak the closure
- let _p: ~proc():Send = cast::transmute(arg);
+ let _p: Box<proc():Send> = cast::transmute(arg);
fail!("failed to spawn native thread: {}", os::last_os_error());
}
return ret;
use libc;
use mem;
use os;
+ use owned::Box;
use ptr;
use rt::stack::RED_ZONE;
pub type rust_thread = libc::pthread_t;
pub type rust_thread_return = *u8;
- pub unsafe fn create(stack: uint, p: ~proc():Send) -> rust_thread {
+ pub unsafe fn create(stack: uint, p: Box<proc():Send>) -> rust_thread {
let mut native: libc::pthread_t = mem::uninit();
let mut attr: libc::pthread_attr_t = mem::uninit();
assert_eq!(pthread_attr_init(&mut attr), 0);
if ret != 0 {
// be sure to not leak the closure
- let _p: ~proc():Send = cast::transmute(arg);
+ let _p: Box<proc():Send> = cast::transmute(arg);
fail!("failed to spawn native thread: {}", os::last_os_error());
}
native
#![allow(dead_code)]
+#[cfg(test)]
+use owned::Box;
#[cfg(unix)]
use libc::c_int;
#[cfg(unix)]
let value = box 20;
create(&mut key);
set(key, transmute(value));
- let value: ~int = transmute(get(key));
+ let value: Box<int> = transmute(get(key));
assert_eq!(value, box 20);
let value = box 30;
set(key, transmute(value));
- let value: ~int = transmute(get(key));
+ let value: Box<int> = transmute(get(key));
assert_eq!(value, box 30);
}
}
use kinds::Send;
use mem;
use option::{Some, None, Option};
+use owned::Box;
use prelude::drop;
use ptr::RawPtr;
use result::{Err, Ok};
pub struct Unwinder {
unwinding: bool,
- cause: Option<~Any:Send>
+ cause: Option<Box<Any:Send>>
}
impl Unwinder {
}
}
- pub fn begin_unwind(&mut self, cause: ~Any:Send) -> ! {
+ pub fn begin_unwind(&mut self, cause: Box<Any:Send>) -> ! {
rtdebug!("begin_unwind()");
self.unwinding = true;
exception: *uw::_Unwind_Exception) {
rtdebug!("exception_cleanup()");
unsafe {
- let _: ~uw::_Unwind_Exception = cast::transmute(exception);
+ let _: Box<uw::_Unwind_Exception> =
+ cast::transmute(exception);
}
}
}
/// Do this split took the LLVM IR line counts of `fn main() { fail!()
/// }` from ~1900/3700 (-O/no opts) to 180/590.
#[inline(never)] #[cold] // this is the slow path, please never inline this
-fn begin_unwind_inner(msg: ~Any:Send, file: &'static str, line: uint) -> ! {
+fn begin_unwind_inner(msg: Box<Any:Send>,
+ file: &'static str,
+ line: uint) -> ! {
let mut task;
{
let msg_s = match msg.as_ref::<&'static str>() {
Some(s) => *s,
None => match msg.as_ref::<~str>() {
Some(s) => s.as_slice(),
- None => "~Any",
+ None => "Box<Any>",
}
};
// order to get some better diagnostics, we print on failure and
// immediately abort the whole process if there is no local task
// available.
- let opt_task: Option<~Task> = Local::try_take();
+ let opt_task: Option<Box<Task>> = Local::try_take();
task = match opt_task {
Some(t) => t,
None => {
```rust
let int_vector = [1,2,3];
let str_vector = ["one", "two", "three"];
- ```
+```
This is a big module, but for a high-level overview:
let numbers = [0, 1, 2];
let last_numbers = numbers.slice(1, 3);
// last_numbers is now &[1, 2]
- ```
+```
Traits defined for the `~[T]` type, like `OwnedVector`, can only be called
on such vectors. These methods deal with adding elements or otherwise changing
let mut numbers = vec![0, 1, 2];
numbers.push(7);
// numbers is now vec![0, 1, 2, 7];
- ```
+```
## Implementations of other traits
for &x in numbers.iter() {
println!("{} is a number!", x);
}
- ```
+```
* `.mut_iter()` returns an iterator that allows modifying each value.
* `.move_iter()` converts an owned vector into an iterator that
#[cfg(test)]
mod tests {
use prelude::*;
- use mem;
- use slice::*;
use cmp::*;
+ use mem;
+ use owned::Box;
use rand::{Rng, task_rng};
+ use slice::*;
fn square(n: uint) -> uint { n * n }
let mut v2 = vec![box 1, box 2, box 3, box 3];
v2.dedup();
/*
- * If the ~pointers were leaked or otherwise misused, valgrind and/or
- * rustrt should raise errors.
+ * If the boxed pointers were leaked or otherwise misused, valgrind
+ * and/or rustrt should raise errors.
*/
}
struct S {
f: Cell<int>,
- boxes: (~int, Rc<int>)
+ boxes: (Box<int>, Rc<int>)
}
impl Clone for S {
}
assert_eq!(cnt, 11);
- let xs = vec![Foo, Foo, Foo];
- assert_eq!(format!("{:?}", xs.slice(0, 2).to_owned()),
- "~[slice::tests::Foo, slice::tests::Foo]".to_owned());
-
let xs: [Foo, ..3] = [Foo, Foo, Foo];
- assert_eq!(format!("{:?}", xs.slice(0, 2).to_owned()),
- "~[slice::tests::Foo, slice::tests::Foo]".to_owned());
cnt = 0;
for f in xs.iter() {
assert!(*f == Foo);
there are two common kinds of strings in Rust:
* `~str` - This is an owned string. This type obeys all of the normal semantics
- of the `~T` types, meaning that it has one, and only one, owner. This
- type cannot be implicitly copied, and is moved out of when passed to
- other functions.
+ of the `Box<T>` types, meaning that it has one, and only one,
+ owner. This type cannot be implicitly copied, and is moved out of
+ when passed to other functions.
* `&str` - This is the borrowed string type. This type of string can only be
created from the other kind of string. As the name "borrowed"
let borrowed_string1 = "This string is borrowed with the 'static lifetime";
let borrowed_string2: &str = owned_string; // owned strings can be borrowed
}
- ```
+```
From the example above, you can see that Rust has 2 different kinds of string
literals. The owned literals correspond to the owned string types, but the
use iter::Iterator;
use kinds::Send;
use ops::Drop;
+use owned::Box;
use ptr::RawPtr;
use sync::atomics::{fence, AtomicUint, Relaxed, Acquire, Release};
use ty::Unsafe;
// happened before), and an "acquire" operation before deleting the object.
// [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
fence(Acquire);
- let _: ~ArcData<T> = cast::transmute(self.data);
+ let _: Box<ArcData<T>> = cast::transmute(self.data);
}
}
}
//! }
//! });
//!
-//! shared_big_object.swap(~BigObject, SeqCst);
+//! shared_big_object.swap(box BigObject, SeqCst);
//! }
//! ```
//!
use std::kinds::marker;
use option::{Option,Some,None};
use ops::Drop;
+use owned::Box;
use ty::Unsafe;
/// An atomic boolean type.
impl<T> AtomicOption<T> {
/// Create a new `AtomicOption`
- pub fn new(p: ~T) -> AtomicOption<T> {
+ pub fn new(p: Box<T>) -> AtomicOption<T> {
unsafe { AtomicOption { p: Unsafe::new(cast::transmute(p)) } }
}
/// Store a value, returning the old value
#[inline]
- pub fn swap(&self, val: ~T, order: Ordering) -> Option<~T> {
+ pub fn swap(&self, val: Box<T>, order: Ordering) -> Option<Box<T>> {
unsafe {
let val = cast::transmute(val);
/// Remove the value, leaving the `AtomicOption` empty.
#[inline]
- pub fn take(&self, order: Ordering) -> Option<~T> {
+ pub fn take(&self, order: Ordering) -> Option<Box<T>> {
unsafe { self.swap(cast::transmute(0), order) }
}
/// the option was already `Some`, returns `Some` of the rejected
/// value.
#[inline]
- pub fn fill(&self, val: ~T, order: Ordering) -> Option<~T> {
+ pub fn fill(&self, val: Box<T>, order: Ordering) -> Option<Box<T>> {
unsafe {
let val = cast::transmute(val);
let expected = cast::transmute(0);
use mem;
use ops::Drop;
use option::{Option, Some, None};
+use owned::Box;
use ptr;
use ptr::RawPtr;
use sync::arc::UnsafeArc;
/// will only use this structure when allocating a new buffer or deallocating a
/// previous one.
pub struct BufferPool<T> {
- pool: Exclusive<Vec<~Buffer<T>>>,
+ pool: Exclusive<Vec<Box<Buffer<T>>>>,
}
/// An internal buffer used by the chase-lev deque. This structure is actually
(Worker { deque: a }, Stealer { deque: b })
}
- fn alloc(&mut self, bits: int) -> ~Buffer<T> {
+ fn alloc(&mut self, bits: int) -> Box<Buffer<T>> {
unsafe {
self.pool.with(|pool| {
match pool.iter().position(|x| x.size() >= (1 << bits)) {
}
}
- fn free(&mut self, buf: ~Buffer<T>) {
+ fn free(&mut self, buf: Box<Buffer<T>>) {
unsafe {
let mut buf = Some(buf);
self.pool.with(|pool| {
use super::{Data, BufferPool, Abort, Empty, Worker, Stealer};
use cast;
+ use owned::Box;
use rt::thread::Thread;
use rand;
use rand::Rng;
t.join();
}
- fn stampede(mut w: Worker<~int>, s: Stealer<~int>,
+ fn stampede(mut w: Worker<Box<int>>, s: Stealer<Box<int>>,
nthreads: int, amt: uint) {
for _ in range(0, amt) {
w.push(box 20);
let mut s = s;
while (*unsafe_remaining).load(SeqCst) > 0 {
match s.steal() {
- Data(~20) => {
+ Data(box 20) => {
(*unsafe_remaining).fetch_sub(1, SeqCst);
}
Data(..) => fail!(),
while remaining.load(SeqCst) > 0 {
match w.pop() {
- Some(~20) => { remaining.fetch_sub(1, SeqCst); }
+ Some(box 20) => { remaining.fetch_sub(1, SeqCst); }
Some(..) => fail!(),
None => {}
}
#[test]
fn run_stampede() {
- let mut pool = BufferPool::<~int>::new();
+ let mut pool = BufferPool::<Box<int>>::new();
let (w, s) = pool.deque();
stampede(w, s, 8, 10000);
}
#[test]
fn many_stampede() {
static AMT: uint = 4;
- let mut pool = BufferPool::<~int>::new();
+ let mut pool = BufferPool::<Box<int>>::new();
let threads = range(0, AMT).map(|_| {
let (w, s) = pool.deque();
Thread::start(proc() {
let s = s.clone();
let unique_box = box AtomicUint::new(0);
let thread_box = unsafe {
- *cast::transmute::<&~AtomicUint,**mut AtomicUint>(&unique_box)
+ *cast::transmute::<&Box<AtomicUint>,
+ **mut AtomicUint>(&unique_box)
};
(Thread::start(proc() {
unsafe {
use kinds::Send;
use ops::Drop;
use option::{Option, None, Some};
+use owned::Box;
use ptr::RawPtr;
use sync::atomics::{AtomicPtr, Release, Acquire, AcqRel, Relaxed};
assert!((*tail).value.is_none());
assert!((*next).value.is_some());
let ret = (*next).value.take_unwrap();
- let _: ~Node<T> = cast::transmute(tail);
+ let _: Box<Node<T>> = cast::transmute(tail);
return Data(ret);
}
let mut cur = self.tail;
while !cur.is_null() {
let next = (*cur).next.load(Relaxed);
- let _: ~Node<T> = cast::transmute(cur);
+ let _: Box<Node<T>> = cast::transmute(cur);
cur = next;
}
}
use kinds::Send;
use ops::Drop;
use option::{Some, None, Option};
+use owned::Box;
use ptr::RawPtr;
use sync::atomics::{AtomicPtr, Relaxed, AtomicUint, Acquire, Release};
(*self.tail_prev.load(Relaxed)).next.store(next, Relaxed);
// We have successfully erased all references to 'tail', so
// now we can safely drop it.
- let _: ~Node<T> = cast::transmute(tail);
+ let _: Box<Node<T>> = cast::transmute(tail);
}
}
return ret;
let mut cur = self.first;
while !cur.is_null() {
let next = (*cur).next.load(Relaxed);
- let _n: ~Node<T> = cast::transmute(cur);
+ let _n: Box<Node<T>> = cast::transmute(cur);
cur = next;
}
}
use io::Writer;
use kinds::{Send, marker};
use option::{None, Some, Option};
+use owned::Box;
use result::{Result, Ok, Err};
use rt::local::Local;
use rt::task::Task;
///
/// If you wish for this result's delivery to block until all
/// children tasks complete, recommend using a result future.
-pub type TaskResult = Result<(), ~Any:Send>;
+pub type TaskResult = Result<(), Box<Any:Send>>;
/// Task configuration options
pub struct TaskOpts {
/// The size of the stack for the spawned task
pub stack_size: Option<uint>,
/// Task-local stdout
- pub stdout: Option<~Writer:Send>,
+ pub stdout: Option<Box<Writer:Send>>,
/// Task-local stderr
- pub stderr: Option<~Writer:Send>,
+ pub stderr: Option<Box<Writer:Send>>,
}
/**
Some(gen) => gen(f),
None => f
};
- let t: ~Task = Local::take();
+ let t: Box<Task> = Local::take();
t.spawn_sibling(self.opts, f);
}
* # Failure
* Fails if a future_result was already set for this task.
*/
- pub fn try<T:Send>(mut self, f: proc():Send -> T) -> Result<T, ~Any:Send> {
+ pub fn try<T:Send>(mut self, f: proc():Send -> T)
+ -> Result<T, Box<Any:Send>> {
let (tx, rx) = channel();
let result = self.future_result();
/// the function or an error if the task failed
///
/// This is equivalent to TaskBuilder::new().try
-pub fn try<T:Send>(f: proc():Send -> T) -> Result<T, ~Any:Send> {
+pub fn try<T:Send>(f: proc():Send -> T) -> Result<T, Box<Any:Send>> {
TaskBuilder::new().try(f)
}
use rt::local::Local;
// FIXME(#7544): Optimize this, since we know we won't block.
- let task: ~Task = Local::take();
+ let task: Box<Task> = Local::take();
task.yield_now();
}
#[test]
fn test_try_fail_message_any() {
match try(proc() {
- fail!(box 413u16 as ~Any:Send);
+ fail!(box 413u16 as Box<Any:Send>);
}) {
Err(e) => {
- type T = ~Any:Send;
+ type T = Box<Any:Send>;
assert!(e.is::<T>());
let any = e.move::<T>().unwrap();
assert!(any.is::<u16>());
/// # Example
///
/// ```rust
- /// let mut vec = vec!(~1);
- /// vec.push_all_move(vec!(~2, ~3, ~4));
- /// assert_eq!(vec, vec!(~1, ~2, ~3, ~4));
+ /// let mut vec = vec!(box 1);
+ /// vec.push_all_move(vec!(box 2, box 3, box 4));
+ /// assert_eq!(vec, vec!(box 1, box 2, box 3, box 4));
/// ```
pub fn push_all_move(&mut self, other: Vec<T>) {
self.extend(other.move_iter());
// After we've failed the fast path, then we delegate to the differnet
// locking protocols for green/native tasks. This will select two tasks
// to continue further (one native, one green).
- let t: ~Task = Local::take();
+ let t: Box<Task> = Local::take();
let can_block = t.can_block();
let native_bit;
if can_block {
// regularly in native/green contention. Due to try_lock and the header
// of lock stealing the lock, it's also possible for native/native
// contention to hit this location, but as less common.
- let t: ~Task = Local::take();
+ let t: Box<Task> = Local::take();
t.deschedule(1, |task| {
let task = unsafe { task.cast_to_uint() };
// Tasks which can block are super easy. These tasks just call the blocking
// `lock()` function on an OS mutex
- fn native_lock(&self, t: ~Task) {
+ fn native_lock(&self, t: Box<Task>) {
Local::put(t);
unsafe { self.lock.lock_noguard(); }
}
unsafe { self.lock.unlock_noguard(); }
}
- fn green_lock(&self, t: ~Task) {
+ fn green_lock(&self, t: Box<Task>) {
// Green threads flag their presence with an atomic counter, and if they
// fail to be the first to the mutex, they enqueue themselves on a
// concurrent internal queue with a stack-allocated node.
#[unsafe_destructor]
impl<Q: Send> Drop for Sem<Q> {
fn drop(&mut self) {
- let _waiters: ~SemInner<Q> = unsafe { cast::transmute(self.inner) };
+ let _waiters: Box<SemInner<Q>> = unsafe {
+ cast::transmute(self.inner)
+ };
self.inner = 0 as *();
}
}
let m = Arc::new(Mutex::new());
let m2 = m.clone();
- let result: result::Result<(), ~Any:Send> = task::try(proc() {
+ let result: result::Result<(), Box<Any:Send>> = task::try(proc() {
let _lock = m2.lock();
fail!();
});
let x = Arc::new(RWLock::new());
let x2 = x.clone();
- let result: result::Result<(), ~Any:Send> = task::try(proc() {
+ let result: result::Result<(), Box<Any:Send>> = task::try(proc() {
lock_rwlock_in_mode(&x2, mode1, || {
fail!();
})
pub fn unop_to_str(op: UnOp) -> &'static str {
match op {
UnBox => "@",
- UnUniq => "~",
+ UnUniq => "box() ",
UnDeref => "*",
UnNot => "!",
UnNeg => "-",
// others log errors for later reporting.
pub struct Handler {
err_count: Cell<uint>,
- emit: RefCell<~Emitter:Send>,
+ emit: RefCell<Box<Emitter:Send>>,
}
impl Handler {
mk_handler(box EmitterWriter::stderr())
}
-pub fn mk_handler(e: ~Emitter:Send) -> Handler {
+pub fn mk_handler(e: Box<Emitter:Send>) -> Handler {
Handler {
err_count: Cell::new(0),
emit: RefCell::new(e),
enum Destination {
Terminal(term::Terminal<io::stdio::StdWriter>),
- Raw(~Writer:Send),
+ Raw(Box<Writer:Send>),
}
impl EmitterWriter {
}
}
- pub fn new(dst: ~Writer:Send) -> EmitterWriter {
+ pub fn new(dst: Box<Writer:Send>) -> EmitterWriter {
EmitterWriter { dst: Raw(dst) }
}
}
use parse::token::InternedString;
use parse::token;
+
enum State {
Asm,
Outputs,
static OPTIONS: &'static [&'static str] = &["volatile", "alignstack", "intel"];
pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
let mut p = parse::new_parser_from_tts(cx.parse_sess(),
cx.cfg(),
tts.iter()
ecx: &mut ExtCtxt,
span: Span,
token_tree: &[ast::TokenTree])
- -> ~MacResult;
+ -> Box<MacResult>;
}
pub type MacroExpanderFn =
fn(ecx: &mut ExtCtxt, span: codemap::Span, token_tree: &[ast::TokenTree])
- -> ~MacResult;
+ -> Box<MacResult>;
impl MacroExpander for BasicMacroExpander {
fn expand(&self,
ecx: &mut ExtCtxt,
span: Span,
token_tree: &[ast::TokenTree])
- -> ~MacResult {
+ -> Box<MacResult> {
(self.expander)(ecx, span, token_tree)
}
}
sp: Span,
ident: ast::Ident,
token_tree: Vec<ast::TokenTree> )
- -> ~MacResult;
+ -> Box<MacResult>;
}
impl IdentMacroExpander for BasicIdentMacroExpander {
sp: Span,
ident: ast::Ident,
token_tree: Vec<ast::TokenTree> )
- -> ~MacResult {
+ -> Box<MacResult> {
(self.expander)(cx, sp, ident, token_tree)
}
}
pub type IdentMacroExpanderFn =
- fn(&mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree> ) -> ~MacResult;
+ fn(&mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult>;
pub type MacroCrateRegistrationFun =
fn(|ast::Name, SyntaxExtension|);
e: @ast::Expr
}
impl MacExpr {
- pub fn new(e: @ast::Expr) -> ~MacResult {
- box MacExpr { e: e } as ~MacResult
+ pub fn new(e: @ast::Expr) -> Box<MacResult> {
+ box MacExpr { e: e } as Box<MacResult>
}
}
impl MacResult for MacExpr {
i: @ast::Item
}
impl MacItem {
- pub fn new(i: @ast::Item) -> ~MacResult {
- box MacItem { i: i } as ~MacResult
+ pub fn new(i: @ast::Item) -> Box<MacResult> {
+ box MacItem { i: i } as Box<MacResult>
}
}
impl MacResult for MacItem {
///
/// Use this as a return value after hitting any errors and
/// calling `span_err`.
- pub fn any(sp: Span) -> ~MacResult {
- box DummyResult { expr_only: false, span: sp } as ~MacResult
+ pub fn any(sp: Span) -> Box<MacResult> {
+ box DummyResult { expr_only: false, span: sp } as Box<MacResult>
}
/// Create a default MacResult that can only be an expression.
/// Use this for macros that must expand to an expression, so even
/// if an error is encountered internally, the user will recieve
/// an error that they also used it in the wrong place.
- pub fn expr(sp: Span) -> ~MacResult {
- box DummyResult { expr_only: true, span: sp } as ~MacResult
+ pub fn expr(sp: Span) -> Box<MacResult> {
+ box DummyResult { expr_only: true, span: sp } as Box<MacResult>
}
/// A plain dummy expression.
/// A normal, function-like syntax extension.
///
/// `bytes!` is a `NormalTT`.
- NormalTT(~MacroExpander:'static, Option<Span>),
+ NormalTT(Box<MacroExpander:'static>, Option<Span>),
/// A function-like syntax extension that has an extra ident before
/// the block.
///
/// `macro_rules!` is an `IdentTT`.
- IdentTT(~IdentMacroExpander:'static, Option<Span>),
+ IdentTT(Box<IdentMacroExpander:'static>, Option<Span>),
}
pub struct BlockInfo {
use ext::base;
use ext::build::AstBuilder;
-pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
+
+pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+ -> Box<base::MacResult> {
// Gather all argument expressions
let exprs = match get_exprs_from_tts(cx, sp, tts) {
None => return DummyResult::expr(sp),
use parse::token;
use parse;
-pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
+
+pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
+ -> Box<base::MacResult> {
let mut p = parse::new_parser_from_tts(cx.parse_sess(),
cx.cfg(),
tts.iter()
pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
sp: codemap::Span,
- tts: &[ast::TokenTree]) -> ~base::MacResult {
+ tts: &[ast::TokenTree])
+ -> Box<base::MacResult> {
let es = match base::get_exprs_from_tts(cx, sp, tts) {
Some(e) => e,
None => return base::DummyResult::expr(sp)
use std::strbuf::StrBuf;
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
let mut res_str = StrBuf::new();
for (i, e) in tts.iter().enumerate() {
if i & 1 == 1 {
Self if nonstatic => {
self_args.push(arg_expr);
}
- Ptr(~Self, _) if nonstatic => {
+ Ptr(box Self, _) if nonstatic => {
self_args.push(cx.expr_deref(trait_.span, arg_expr))
}
_ => {
use codemap::{Span,respan};
use owned_slice::OwnedSlice;
+
/// The types of pointers
pub enum PtrTy<'a> {
Send, // ~
pub struct Path<'a> {
pub path: Vec<&'a str> ,
pub lifetime: Option<&'a str>,
- pub params: Vec<~Ty<'a>> ,
+ pub params: Vec<Box<Ty<'a>>>,
pub global: bool,
}
}
pub fn new_<'r>(path: Vec<&'r str> ,
lifetime: Option<&'r str>,
- params: Vec<~Ty<'r>> ,
+ params: Vec<Box<Ty<'r>>>,
global: bool)
-> Path<'r> {
Path {
/// A type. Supports pointers (except for *), Self, and literals
pub enum Ty<'a> {
Self,
- // &/~/@ Ty
- Ptr(~Ty<'a>, PtrTy<'a>),
+ // &/Box/@ Ty
+ Ptr(Box<Ty<'a>>, PtrTy<'a>),
// mod::mod::Type<[lifetime], [Params...]>, including a plain type
// parameter, and things like `int`
Literal(Path<'a>),
pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
Borrowed(None, ast::MutImmutable)
}
-pub fn borrowed<'r>(ty: ~Ty<'r>) -> Ty<'r> {
+pub fn borrowed<'r>(ty: Box<Ty<'r>>) -> Ty<'r> {
Ptr(ty, borrowed_ptrty())
}
use std::os;
pub fn expand_option_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") {
None => return DummyResult::expr(sp),
Some(v) => v
}
pub fn expand_env(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
let exprs = match get_exprs_from_tts(cx, sp, tts) {
Some(ref exprs) if exprs.len() == 0 => {
cx.span_err(sp, "env! takes 1 or 2 arguments");
}
}
- //fn fake_print_crate(krate: &ast::Crate) {
- // let mut out = ~std::io::stderr() as ~std::io::Writer;
- // let mut s = pprust::rust_printer(out, get_ident_interner());
- // pprust::print_crate_(&mut s, krate);
- //}
-
fn expand_crate_str(crate_str: ~str) -> ast::Crate {
let ps = parse::new_parse_sess();
let crate_ast = string_to_parser(&ps, crate_str).parse_crate_mod();
use ext::base;
use ext::build::AstBuilder;
-pub fn expand_syntax_ext(ecx: &mut base::ExtCtxt, sp: Span,
- _tts: &[ast::TokenTree]) -> ~base::MacResult {
+
+pub fn expand_syntax_ext(ecx: &mut base::ExtCtxt,
+ sp: Span,
+ _tts: &[ast::TokenTree])
+ -> Box<base::MacResult> {
ecx.span_err(sp, "`fmt!` is deprecated, use `format!` instead");
ecx.parse_sess.span_diagnostic.span_note(sp,
"see http://static.rust-lang.org/doc/master/std/fmt/index.html \
}
pub fn expand_args(ecx: &mut ExtCtxt, sp: Span,
- tts: &[ast::TokenTree]) -> ~base::MacResult {
+ tts: &[ast::TokenTree]) -> Box<base::MacResult> {
match parse_args(ecx, sp, tts) {
(extra, Some((efmt, args, order, names))) => {
pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
sp: codemap::Span,
tt: &[ast::TokenTree])
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
cx.print_backtrace();
println!("{}", print::pprust::tt_to_str(&ast::TTDelim(
use parse::token;
use parse;
+
/**
*
* Quasiquoting works via token trees.
pub fn expand_quote_tokens(cx: &mut ExtCtxt,
sp: Span,
- tts: &[ast::TokenTree]) -> ~base::MacResult {
+ tts: &[ast::TokenTree])
+ -> Box<base::MacResult> {
let (cx_expr, expr) = expand_tts(cx, sp, tts);
let expanded = expand_wrapper(cx, sp, cx_expr, expr);
base::MacExpr::new(expanded)
pub fn expand_quote_expr(cx: &mut ExtCtxt,
sp: Span,
- tts: &[ast::TokenTree]) -> ~base::MacResult {
+ tts: &[ast::TokenTree]) -> Box<base::MacResult> {
let expanded = expand_parse_call(cx, sp, "parse_expr", Vec::new(), tts);
base::MacExpr::new(expanded)
}
pub fn expand_quote_item(cx: &mut ExtCtxt,
sp: Span,
- tts: &[ast::TokenTree]) -> ~base::MacResult {
+ tts: &[ast::TokenTree])
+ -> Box<base::MacResult> {
let e_attrs = cx.expr_vec_ng(sp);
let expanded = expand_parse_call(cx, sp, "parse_item",
vec!(e_attrs), tts);
pub fn expand_quote_pat(cx: &mut ExtCtxt,
sp: Span,
- tts: &[ast::TokenTree]) -> ~base::MacResult {
+ tts: &[ast::TokenTree])
+ -> Box<base::MacResult> {
let e_refutable = cx.expr_lit(sp, ast::LitBool(true));
let expanded = expand_parse_call(cx, sp, "parse_pat",
vec!(e_refutable), tts);
pub fn expand_quote_ty(cx: &mut ExtCtxt,
sp: Span,
- tts: &[ast::TokenTree]) -> ~base::MacResult {
+ tts: &[ast::TokenTree])
+ -> Box<base::MacResult> {
let e_param_colons = cx.expr_lit(sp, ast::LitBool(false));
let expanded = expand_parse_call(cx, sp, "parse_ty",
vec!(e_param_colons), tts);
pub fn expand_quote_stmt(cx: &mut ExtCtxt,
sp: Span,
- tts: &[ast::TokenTree]) -> ~base::MacResult {
+ tts: &[ast::TokenTree])
+ -> Box<base::MacResult> {
let e_attrs = cx.expr_vec_ng(sp);
let expanded = expand_parse_call(cx, sp, "parse_stmt",
vec!(e_attrs), tts);
/* line!(): expands to the current line number */
pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
base::check_zero_tts(cx, sp, tts, "line!");
let topmost = topmost_expn_info(cx.backtrace().unwrap());
/* col!(): expands to the current column number */
pub fn expand_col(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
base::check_zero_tts(cx, sp, tts, "col!");
let topmost = topmost_expn_info(cx.backtrace().unwrap());
/* The filemap (`loc.file`) contains a bunch more information we could spit
* out if we wanted. */
pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
base::check_zero_tts(cx, sp, tts, "file!");
let topmost = topmost_expn_info(cx.backtrace().unwrap());
}
pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
let s = pprust::tts_to_str(tts);
base::MacExpr::new(cx.expr_str(sp, token::intern_and_get_ident(s)))
}
pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
base::check_zero_tts(cx, sp, tts, "module_path!");
let string = cx.mod_path()
.iter()
// This is generally a bad idea because it's going to behave
// unhygienically.
pub fn expand_include(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
let file = match get_single_str_from_tts(cx, sp, tts, "include!") {
Some(f) => f,
None => return DummyResult::expr(sp),
// include_str! : read the given file, insert it as a literal string expr
pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") {
Some(f) => f,
None => return DummyResult::expr(sp)
}
pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
- -> ~base::MacResult
-{
+ -> Box<base::MacResult> {
let file = match get_single_str_from_tts(cx, sp, tts, "include_bin!") {
Some(f) => f,
None => return DummyResult::expr(sp)
use ext::base;
use parse::token::{keywords, is_keyword};
+
pub fn expand_trace_macros(cx: &mut ExtCtxt,
sp: Span,
tt: &[ast::TokenTree])
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
match tt {
[ast::TTTok(_, ref tok)] if is_keyword(keywords::True, tok) => {
cx.set_trace_macros(true);
elts: Vec<ast::Matcher> , // maybe should be <'>? Need to understand regions.
sep: Option<Token>,
idx: uint,
- up: Option<~MatcherPos>,
+ up: Option<Box<MatcherPos>>,
matches: Vec<Vec<Rc<NamedMatch>>>,
match_lo: uint, match_hi: uint,
sp_lo: BytePos,
}
pub fn initial_matcher_pos(ms: Vec<Matcher> , sep: Option<Token>, lo: BytePos)
- -> ~MatcherPos {
+ -> Box<MatcherPos> {
let mut match_idx_hi = 0u;
for elt in ms.iter() {
match elt.node {
cx: &mut ExtCtxt,
sp: Span,
arg: &[ast::TokenTree])
- -> ~MacResult {
+ -> Box<MacResult> {
generic_extension(cx,
sp,
self.name,
arg: &[ast::TokenTree],
lhses: &[Rc<NamedMatch>],
rhses: &[Rc<NamedMatch>])
- -> ~MacResult {
+ -> Box<MacResult> {
if cx.trace_macros() {
println!("{}! \\{ {} \\}",
token::get_ident(name),
// Weird, but useful for X-macros.
return box ParserAnyMacro {
parser: RefCell::new(p),
- } as ~MacResult
+ } as Box<MacResult>
}
Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
best_fail_spot = sp;
sp: Span,
name: Ident,
arg: Vec<ast::TokenTree> )
- -> ~base::MacResult {
+ -> Box<base::MacResult> {
// these spans won't matter, anyways
fn ms(m: Matcher_) -> Matcher {
Spanned {
name: token::get_ident(name).to_str(),
ext: NormalTT(exp, Some(sp))
}))
- } as ~MacResult
+ } as Box<MacResult>
}
/* sidestep the interpolation tricks for ident because
(a) idents can be in lots of places, so it'd be a pain
(b) we actually can, since it's a token. */
- MatchedNonterminal(NtIdent(~sn,b)) => {
+ MatchedNonterminal(NtIdent(box sn, b)) => {
r.cur_span = sp;
r.cur_tok = IDENT(sn,b);
return ret_val;
ObsoleteManagedPattern,
ObsoleteManagedString,
ObsoleteManagedVec,
+ ObsoleteOwnedType,
+ ObsoleteOwnedExpr,
+ ObsoleteOwnedPattern,
}
pub trait ParserObsoleteMethods {
"managed vector",
"use `Rc<~[T]>` instead of a managed vector"
),
+ ObsoleteOwnedType => (
+ "`~` notation for owned pointers",
+ "use `Box<T>` in `std::owned` instead"
+ ),
+ ObsoleteOwnedExpr => (
+ "`~` notation for owned pointer allocation",
+ "use the `box` operator instead of `~`"
+ ),
+ ObsoleteOwnedPattern => (
+ "`~` notation for owned pointer patterns",
+ "use the `box` operator instead of `~`"
+ ),
};
self.report(sp, kind, kind_str, desc);
/* ident is handled by common.rs */
-pub fn Parser<'a>(sess: &'a ParseSess, cfg: ast::CrateConfig, mut rdr: ~Reader:)
+pub fn Parser<'a>(
+ sess: &'a ParseSess,
+ cfg: ast::CrateConfig,
+ mut rdr: Box<Reader:>)
-> Parser<'a> {
let tok0 = rdr.next_token();
let span = tok0.sp;
pub last_span: Span,
pub cfg: CrateConfig,
// the previous token or None (only stashed sometimes).
- pub last_token: Option<~token::Token>,
+ pub last_token: Option<Box<token::Token>>,
pub buffer: [TokenAndSpan, ..4],
pub buffer_start: int,
pub buffer_end: int,
pub tokens_consumed: uint,
pub restriction: restriction,
pub quote_depth: uint, // not (yet) related to the quasiquoter
- pub reader: ~Reader:,
+ pub reader: Box<Reader:>,
pub interner: Rc<token::IdentInterner>,
/// The set of seen errors about obsolete syntax. Used to suppress
/// extra detail when the same error is seen twice
} else if self.token == token::TILDE {
// OWNED POINTER
self.bump();
+ match self.token {
+ token::IDENT(ref ident, _)
+ if "str" == token::get_ident(*ident).get() => {
+ // This is OK (for now).
+ }
+ token::LBRACKET => {} // Also OK.
+ _ => self.obsolete(self.last_span, ObsoleteOwnedType),
+ };
TyUniq(self.parse_ty(false))
} else if self.token == token::BINOP(token::STAR) {
// STAR POINTER (bare pointer?)
_ => None,
};
match found {
- Some(INTERPOLATED(token::NtPath(~path))) => {
+ Some(INTERPOLATED(token::NtPath(box path))) => {
return PathAndBounds {
path: path,
bounds: None,
ex = match e.node {
ExprVec(..) | ExprRepeat(..) => ExprVstore(e, ExprVstoreUniq),
ExprLit(lit) if lit_is_str(lit) => {
+ self.obsolete(self.last_span, ObsoleteOwnedExpr);
ExprVstore(e, ExprVstoreUniq)
}
- _ => self.mk_unary(UnUniq, e)
+ _ => {
+ self.obsolete(self.last_span, ObsoleteOwnedExpr);
+ self.mk_unary(UnUniq, e)
+ }
};
}
token::IDENT(_, _) if self.is_keyword(keywords::Box) => {
let sub = self.parse_pat();
pat = PatUniq(sub);
hi = self.last_span.hi;
+ self.obsolete(self.last_span, ObsoleteOwnedPattern);
return @ast::Pat {
id: ast::DUMMY_NODE_ID,
node: pat,
}
};
- self.eval_src_mod_from_path(file_path,
- outer_attrs.iter().map(|x| *x).collect(),
- id_sp)
+ self.eval_src_mod_from_path(file_path, id_sp)
}
fn eval_src_mod_from_path(&mut self,
path: Path,
- outer_attrs: Vec<ast::Attribute> ,
id_sp: Span) -> (ast::Item_, Vec<ast::Attribute> ) {
let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
match included_mod_stack.iter().position(|p| *p == path) {
&path,
id_sp);
let mod_inner_lo = p0.span.lo;
- let (inner, next) = p0.parse_inner_attrs_and_next();
- let mod_attrs = outer_attrs.append(inner.as_slice());
+ let (mod_attrs, next) = p0.parse_inner_attrs_and_next();
let first_item_outer_attrs = next;
let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs, mod_inner_lo);
self.sess.included_mod_stack.borrow_mut().pop();
NtPat( @ast::Pat),
NtExpr(@ast::Expr),
NtTy( P<ast::Ty>),
- NtIdent(~ast::Ident, bool),
+ NtIdent(Box<ast::Ident>, bool),
NtMeta(@ast::MetaItem), // stuff inside brackets for attributes
- NtPath(~ast::Path),
+ NtPath(Box<ast::Path>),
NtTT( @ast::TokenTree), // needs @ed to break a circularity
NtMatchers(Vec<ast::Matcher> )
}
static SIZE_INFINITY: int = 0xffff;
-pub fn mk_printer(out: ~io::Writer, linewidth: uint) -> Printer {
+pub fn mk_printer(out: Box<io::Writer>, linewidth: uint) -> Printer {
// Yes 3, it makes the ring buffers big enough to never
// fall behind.
let n: uint = 3 * linewidth;
* called 'print'.
*/
pub struct Printer {
- pub out: ~io::Writer,
+ pub out: Box<io::Writer>,
buf_len: uint,
margin: int, // width of lines we're constrained to
space: int, // number of spaces left on line
ann: &'a PpAnn
}
-pub fn rust_printer(writer: ~io::Writer) -> State<'static> {
+pub fn rust_printer(writer: Box<io::Writer>) -> State<'static> {
static NO_ANN: NoAnn = NoAnn;
rust_printer_annotated(writer, &NO_ANN)
}
-pub fn rust_printer_annotated<'a>(writer: ~io::Writer,
+pub fn rust_printer_annotated<'a>(writer: Box<io::Writer>,
ann: &'a PpAnn) -> State<'a> {
State {
s: pp::mk_printer(writer, default_columns),
krate: &ast::Crate,
filename: ~str,
input: &mut io::Reader,
- out: ~io::Writer,
+ out: Box<io::Writer>,
ann: &'a PpAnn,
is_expanded: bool) -> IoResult<()> {
let (cmnts, lits) = comments::gather_comments_and_literals(
// FIXME(pcwalton): A nasty function to extract the string from an `io::Writer`
// that we "know" to be a `MemWriter` that works around the lack of checked
// downcasts.
- let (_, wr): (uint, ~MemWriter) = cast::transmute_copy(&s.s.out);
+ let (_, wr): (uint, Box<MemWriter>) = cast::transmute_copy(&s.s.out);
let result = str::from_utf8_owned(wr.get_ref().to_owned()).unwrap();
cast::forget(wr);
result
pub fn print_expr_vstore(&mut self, t: ast::ExprVstore) -> IoResult<()> {
match t {
- ast::ExprVstoreUniq => word(&mut self.s, "~"),
+ ast::ExprVstoreUniq => word(&mut self.s, "box "),
ast::ExprVstoreSlice => word(&mut self.s, "&"),
ast::ExprVstoreMutSlice => {
try!(word(&mut self.s, "&"));
try!(self.pclose());
}
ast::PatUniq(inner) => {
- try!(word(&mut self.s, "~"));
+ try!(word(&mut self.s, "box "));
try!(self.print_pat(inner));
}
ast::PatRegion(inner) => {
pub struct Terminal<T> {
num_colors: u16,
out: T,
- ti: ~TermInfo
+ ti: Box<TermInfo>,
}
impl<T: Writer> Terminal<T> {
"box1"];
/// Parse a compiled terminfo entry, using long capability names if `longnames` is true
-pub fn parse(file: &mut io::Reader,
- longnames: bool) -> Result<~TermInfo, ~str> {
+pub fn parse(file: &mut io::Reader, longnames: bool)
+ -> Result<Box<TermInfo>, ~str> {
macro_rules! try( ($e:expr) => (
match $e { Ok(e) => e, Err(e) => return Err(format!("{}", e)) }
) )
}
/// Create a dummy TermInfo struct for msys terminals
-pub fn msys_terminfo() -> ~TermInfo {
+pub fn msys_terminfo() -> Box<TermInfo> {
let mut strings = HashMap::new();
strings.insert("sgr0".to_owned(), Vec::from_slice(bytes!("\x1b[0m")));
strings.insert("bold".to_owned(), Vec::from_slice(bytes!("\x1b[1m")));
use std::{os, str};
/// Return path to database entry for `term`
-pub fn get_dbpath_for_term(term: &str) -> Option<~Path> {
+pub fn get_dbpath_for_term(term: &str) -> Option<Box<Path>> {
if term.len() == 0 {
return None;
}
StaticMetricFn(proc(&mut MetricMap)),
DynTestFn(proc():Send),
DynMetricFn(proc(&mut MetricMap)),
- DynBenchFn(~TDynBenchFn)
+ DynBenchFn(Box<TDynBenchFn>)
}
impl TestFn {
#[deriving(Clone, Eq)]
pub struct BenchSamples {
- ns_iter_summ: stats::Summary,
+ ns_iter_summ: stats::Summary<f64>,
mb_s: uint,
}
if nocapture {
drop((stdout, stderr));
} else {
- task.opts.stdout = Some(box stdout as ~Writer:Send);
- task.opts.stderr = Some(box stderr as ~Writer:Send);
+ task.opts.stdout = Some(box stdout as Box<Writer:Send>);
+ task.opts.stderr = Some(box stderr as Box<Writer:Send>);
}
let result_future = task.future_result();
task.spawn(testfn);
}
// This is a more statistics-driven benchmark algorithm
- pub fn auto_bench(&mut self, f: |&mut Bencher|) -> stats::Summary {
+ pub fn auto_bench(&mut self, f: |&mut Bencher|) -> stats::Summary<f64> {
// Initial bench run to get ballpark figure.
let mut n = 1_u64;
use std::io;
use std::mem;
use std::num;
+use std::num::Zero;
use collections::hashmap;
+use std::fmt::Show;
-// NB: this can probably be rewritten in terms of num::Num
-// to be less f64-specific.
-
-fn f64_cmp(x: f64, y: f64) -> Ordering {
+fn local_cmp<T:Float>(x: T, y: T) -> Ordering {
// arbitrarily decide that NaNs are larger than everything.
if y.is_nan() {
Less
}
}
-fn f64_sort(v: &mut [f64]) {
- v.sort_by(|x: &f64, y: &f64| f64_cmp(*x, *y));
+fn local_sort<T: Float>(v: &mut [T]) {
+ v.sort_by(|x: &T, y: &T| local_cmp(*x, *y));
}
/// Trait that provides simple descriptive statistics on a univariate set of numeric samples.
-pub trait Stats {
+pub trait Stats <T: Float + FromPrimitive>{
/// Sum of the samples.
///
/// ["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;
+ fn sum(self) -> T;
/// Minimum value of the samples.
- fn min(self) -> f64;
+ fn min(self) -> T;
/// Maximum value of the samples.
- fn max(self) -> f64;
+ fn max(self) -> T;
/// Arithmetic mean (average) of the samples: sum divided by sample-count.
///
/// See: https://en.wikipedia.org/wiki/Arithmetic_mean
- fn mean(self) -> f64;
+ fn mean(self) -> T;
/// 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;
+ fn median(self) -> T;
/// 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
/// than `n`.
///
/// See: https://en.wikipedia.org/wiki/Variance
- fn var(self) -> f64;
+ fn var(self) -> T;
/// Standard deviation: the square root of the sample variance.
///
/// `median_abs_dev` for unknown distributions.
///
/// See: https://en.wikipedia.org/wiki/Standard_deviation
- fn std_dev(self) -> f64;
+ fn std_dev(self) -> T;
/// 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;
+ fn std_dev_pct(self) -> T;
/// 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
/// deviation.
///
/// See: http://en.wikipedia.org/wiki/Median_absolute_deviation
- fn median_abs_dev(self) -> f64;
+ fn median_abs_dev(self) -> T;
/// Median absolute deviation as a percent of the median. See `median_abs_dev` and `median`.
- fn median_abs_dev_pct(self) -> f64;
+ fn median_abs_dev_pct(self) -> T;
/// 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`
/// Calculated by linear interpolation between closest ranks.
///
/// See: http://en.wikipedia.org/wiki/Percentile
- fn percentile(self, pct: f64) -> f64;
+ fn percentile(self, pct: T) -> T;
/// 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
/// is otherwise equivalent.
///
/// See also: https://en.wikipedia.org/wiki/Quartile
- fn quartiles(self) -> (f64,f64,f64);
+ fn quartiles(self) -> (T,T,T);
/// 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;
+ fn iqr(self) -> T;
}
/// Extracted collection of all the summary statistics of a sample set.
#[deriving(Clone, Eq)]
#[allow(missing_doc)]
-pub struct Summary {
- pub sum: f64,
- pub min: f64,
- pub max: f64,
- pub mean: f64,
- pub median: f64,
- pub var: f64,
- pub std_dev: f64,
- pub std_dev_pct: f64,
- pub median_abs_dev: f64,
- pub median_abs_dev_pct: f64,
- pub quartiles: (f64,f64,f64),
- pub iqr: f64,
+pub struct Summary<T> {
+ pub sum: T,
+ pub min: T,
+ pub max: T,
+ pub mean: T,
+ pub median: T,
+ pub var: T,
+ pub std_dev: T,
+ pub std_dev_pct: T,
+ pub median_abs_dev: T,
+ pub median_abs_dev_pct: T,
+ pub quartiles: (T,T,T),
+ pub iqr: T,
}
-impl Summary {
+impl<T: Float + FromPrimitive> Summary<T> {
/// Construct a new summary of a sample set.
- pub fn new(samples: &[f64]) -> Summary {
+ pub fn new(samples: &[T]) -> Summary<T> {
Summary {
sum: samples.sum(),
min: samples.min(),
}
}
-impl<'a> Stats for &'a [f64] {
+impl<'a,T: Float + FromPrimitive> Stats<T> for &'a [T] {
// FIXME #11059 handle NaN, inf and overflow
#[allow(deprecated_owned_vector)]
- fn sum(self) -> f64 {
+ fn sum(self) -> T {
let mut partials = vec![];
for &mut x in self.iter() {
// `lo`. Together `hi+lo` are exactly equal to `x+y`.
let hi = x + y;
let lo = y - (hi - x);
- if lo != 0f64 {
+ if !lo.is_zero() {
*partials.get_mut(j) = lo;
j += 1;
}
partials.truncate(j+1);
}
}
- partials.iter().fold(0.0, |p, q| p + *q)
+ let zero: T = Zero::zero();
+ partials.iter().fold(zero, |p, q| p + *q)
}
- fn min(self) -> f64 {
+ fn min(self) -> T {
assert!(self.len() != 0);
self.iter().fold(self[0], |p, q| p.min(*q))
}
- fn max(self) -> f64 {
+ fn max(self) -> T {
assert!(self.len() != 0);
self.iter().fold(self[0], |p, q| p.max(*q))
}
- fn mean(self) -> f64 {
+ fn mean(self) -> T {
assert!(self.len() != 0);
- self.sum() / (self.len() as f64)
+ self.sum() / FromPrimitive::from_uint(self.len()).unwrap()
}
- fn median(self) -> f64 {
- self.percentile(50.0)
+ fn median(self) -> T {
+ self.percentile(FromPrimitive::from_uint(50).unwrap())
}
- fn var(self) -> f64 {
+ fn var(self) -> T {
if self.len() < 2 {
- 0.0
+ Zero::zero()
} else {
let mean = self.mean();
- let mut v = 0.0;
+ let mut v: T = Zero::zero();
for s in self.iter() {
let x = *s - mean;
- v += x*x;
+ v = 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)
+ let denom = FromPrimitive::from_uint(self.len()-1).unwrap();
+ v/denom
}
}
- fn std_dev(self) -> f64 {
+ fn std_dev(self) -> T {
self.var().sqrt()
}
- fn std_dev_pct(self) -> f64 {
- (self.std_dev() / self.mean()) * 100.0
+ fn std_dev_pct(self) -> T {
+ let hundred = FromPrimitive::from_uint(100).unwrap();
+ (self.std_dev() / self.mean()) * hundred
}
- fn median_abs_dev(self) -> f64 {
+ fn median_abs_dev(self) -> T {
let med = self.median();
- let abs_devs: Vec<f64> = self.iter().map(|&v| num::abs(med - v)).collect();
+ let abs_devs: Vec<T> = self.iter().map(|&v| num::abs(med - v)).collect();
// 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.as_slice().median() * 1.4826
+ let number = FromPrimitive::from_f64(1.4826).unwrap();
+ abs_devs.as_slice().median() * number
}
- fn median_abs_dev_pct(self) -> f64 {
- (self.median_abs_dev() / self.median()) * 100.0
+ fn median_abs_dev_pct(self) -> T {
+ let hundred = FromPrimitive::from_uint(100).unwrap();
+ (self.median_abs_dev() / self.median()) * hundred
}
- fn percentile(self, pct: f64) -> f64 {
+ fn percentile(self, pct: T) -> T {
let mut tmp = Vec::from_slice(self);
- f64_sort(tmp.as_mut_slice());
+ local_sort(tmp.as_mut_slice());
percentile_of_sorted(tmp.as_slice(), pct)
}
- fn quartiles(self) -> (f64,f64,f64) {
+ fn quartiles(self) -> (T,T,T) {
let mut tmp = Vec::from_slice(self);
- f64_sort(tmp.as_mut_slice());
- let a = percentile_of_sorted(tmp.as_slice(), 25.0);
- let b = percentile_of_sorted(tmp.as_slice(), 50.0);
- let c = percentile_of_sorted(tmp.as_slice(), 75.0);
+ local_sort(tmp.as_mut_slice());
+ let first = FromPrimitive::from_uint(25).unwrap();
+ let a = percentile_of_sorted(tmp.as_slice(), first);
+ let secound = FromPrimitive::from_uint(50).unwrap();
+ let b = percentile_of_sorted(tmp.as_slice(), secound);
+ let third = FromPrimitive::from_uint(75).unwrap();
+ let c = percentile_of_sorted(tmp.as_slice(), third);
(a,b,c)
}
- fn iqr(self) -> f64 {
+ fn iqr(self) -> T {
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 {
+fn percentile_of_sorted<T: Float + FromPrimitive>(sorted_samples: &[T],
+ pct: T) -> T {
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 {
+ let zero: T = Zero::zero();
+ assert!(zero <= pct);
+ let hundred = FromPrimitive::from_uint(100).unwrap();
+ assert!(pct <= hundred);
+ if pct == hundred {
return sorted_samples[sorted_samples.len() - 1];
}
- let rank = (pct / 100.0) * ((sorted_samples.len() - 1) as f64);
+ let length = FromPrimitive::from_uint(sorted_samples.len() - 1).unwrap();
+ let rank = (pct / hundred) * length;
let lrank = rank.floor();
let d = rank - lrank;
- let n = lrank as uint;
+ let n = lrank.to_uint().unwrap();
let lo = sorted_samples[n];
let hi = sorted_samples[n+1];
lo + (hi - lo) * d
/// 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) {
+pub fn winsorize<T: Float + FromPrimitive>(samples: &mut [T], pct: T) {
let mut tmp = Vec::from_slice(samples);
- f64_sort(tmp.as_mut_slice());
+ local_sort(tmp.as_mut_slice());
let lo = percentile_of_sorted(tmp.as_slice(), pct);
- let hi = percentile_of_sorted(tmp.as_slice(), 100.0-pct);
+ let hundred: T = FromPrimitive::from_uint(100).unwrap();
+ let hi = percentile_of_sorted(tmp.as_slice(), hundred-pct);
for samp in samples.mut_iter() {
if *samp > hi {
*samp = hi
}
/// 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<()> {
+pub fn write_5_number_summary<T: Float + Show>(w: &mut io::Writer,
+ s: &Summary<T>) -> io::IoResult<()> {
let (q1,q2,q3) = s.quartiles;
write!(w, "(min={}, q1={}, med={}, q3={}, max={})",
s.min,
/// 10 | [--****#******----------] | 40
/// ~~~~
-pub fn write_boxplot(w: &mut io::Writer, s: &Summary,
- width_hint: uint) -> io::IoResult<()> {
+pub fn write_boxplot<T: Float + Show + FromPrimitive>(
+ w: &mut io::Writer,
+ s: &Summary<T>,
+ 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());
+ let ten: T = FromPrimitive::from_uint(10).unwrap();
+ let lomag = ten.powf(s.min.abs().log10().floor());
+ let himag = ten.powf(s.max.abs().log10().floor());
// need to consider when the limit is zero
- let lo = if lomag == 0.0 {
- 0.0
+ let zero: T = Zero::zero();
+ let lo = if lomag.is_zero() {
+ zero
} else {
(s.min / lomag).floor() * lomag
};
- let hi = if himag == 0.0 {
- 0.0
+ let hi = if himag.is_zero() {
+ zero
} else {
(s.max / himag).ceil() * himag
};
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);
+ let range_width = width_hint - overhead_width;
+ let range_float = FromPrimitive::from_uint(range_width).unwrap();
+ let char_step = range / range_float;
try!(write!(w, "{} |", lostr));
while c < range_width && v < s.min {
try!(write!(w, " "));
- v += char_step;
+ v = v + char_step;
c += 1;
}
try!(write!(w, "["));
c += 1;
while c < range_width && v < q1 {
try!(write!(w, "-"));
- v += char_step;
+ v = v + char_step;
c += 1;
}
while c < range_width && v < q2 {
try!(write!(w, "*"));
- v += char_step;
+ v = v + char_step;
c += 1;
}
try!(write!(w, r"\#"));
c += 1;
while c < range_width && v < q3 {
try!(write!(w, "*"));
- v += char_step;
+ v = v + char_step;
c += 1;
}
while c < range_width && v < s.max {
try!(write!(w, "-"));
- v += char_step;
+ v = v + char_step;
c += 1;
}
try!(write!(w, "]"));
while c < range_width {
try!(write!(w, " "));
- v += char_step;
+ v = v + char_step;
c += 1;
}
})
)
- fn check(samples: &[f64], summ: &Summary) {
+ fn check(samples: &[f64], summ: &Summary<f64>) {
let summ2 = Summary::new(samples);
#[test]
fn test_boxplot_nonpositive() {
#[allow(deprecated_owned_vector)]
- fn t(s: &Summary, expected: ~str) {
+ fn t(s: &Summary<f64>, expected: ~str) {
use std::io::MemWriter;
let mut m = MemWriter::new();
write_boxplot(&mut m as &mut io::Writer, s, 30).unwrap();
let uuid1 = Uuid::new_v4();
println!("{}", uuid1.to_str());
}
- ```
+```
# Strings
#[test]
fn test_rand_rand() {
let mut rng = rand::task_rng();
- let u: ~Uuid = rand::Rand::rand(&mut rng);
+ let u: Box<Uuid> = rand::Rand::rand(&mut rng);
let ub = u.as_bytes();
assert!(ub.len() == 16);
--- /dev/null
+Subproject commit 238c4d57cce10d33b05cf52a91fc62a09f31ffbb
+++ /dev/null
-*.o
-libsundown.so*
-sundown
-smartypants
-*.exe
+++ /dev/null
-Contributing to Sundown
-=======================
-
-Do not.
-
-Unfortunately, Sundown is currently frozen as we're working with the Reddit, StackOverflow and Meteor developers to design a formal Markdown standard and parser that will supersede Sundown in all these websites (and in GitHub, of course). Our goal is to deprecate Sundown altogether before the end of the year.
-
-The new parser will be smaller, faster, safer and most importantly, more consistent.
-
-Please stay tuned.
+++ /dev/null
-# Makefile
-
-# Copyright (c) 2009, Natacha Porté
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-DEPDIR=depends
-
-# "Machine-dependent" options
-#MFLAGS=-fPIC
-
-CFLAGS=-c -g -O3 -fPIC -Wall -Werror -Wsign-compare -Isrc -Ihtml
-LDFLAGS=-g -O3 -Wall -Werror
-CC=gcc
-
-
-SUNDOWN_SRC=\
- src/markdown.o \
- src/stack.o \
- src/buffer.o \
- src/autolink.o \
- html/html.o \
- html/html_smartypants.o \
- html/houdini_html_e.o \
- html/houdini_href_e.o
-
-all: libsundown.so sundown smartypants html_blocks
-
-.PHONY: all clean
-
-# libraries
-
-libsundown.so: libsundown.so.1
- ln -f -s $^ $@
-
-libsundown.so.1: $(SUNDOWN_SRC)
- $(CC) $(LDFLAGS) -shared -Wl $^ -o $@
-
-# executables
-
-sundown: examples/sundown.o $(SUNDOWN_SRC)
- $(CC) $(LDFLAGS) $^ -o $@
-
-smartypants: examples/smartypants.o $(SUNDOWN_SRC)
- $(CC) $(LDFLAGS) $^ -o $@
-
-# perfect hashing
-html_blocks: src/html_blocks.h
-
-src/html_blocks.h: html_block_names.txt
- gperf -N find_block_tag -H hash_block_tag -C -c -E --ignore-case $^ > $@
-
-
-# housekeeping
-clean:
- rm -f src/*.o html/*.o examples/*.o
- rm -f libsundown.so libsundown.so.1 sundown smartypants
- rm -f sundown.exe smartypants.exe
- rm -rf $(DEPDIR)
-
-
-# dependencies
-
-include $(wildcard $(DEPDIR)/*.d)
-
-
-# generic object compilations
-
-%.o: src/%.c examples/%.c html/%.c
- @mkdir -p $(DEPDIR)
- @$(CC) -MM $< > $(DEPDIR)/$*.d
- $(CC) $(CFLAGS) -o $@ $<
-
+++ /dev/null
-
-CFLAGS=/O2 /EHsc /I"src/" /I"examples"/ /I"html"/
-CC=cl
-
-SUNDOWN_SRC=\
- src\markdown.obj \
- src\stack.obj \
- src\buffer.obj \
- src\autolink.obj \
- html\html.obj \
- html\html_smartypants.obj \
- html\houdini_html_e.obj \
- html\houdini_href_e.obj
-
-all: sundown.dll sundown.exe
-
-sundown.dll: $(SUNDOWN_SRC) sundown.def
- $(CC) $(SUNDOWN_SRC) sundown.def /link /DLL $(LDFLAGS) /out:$@
-
-sundown.exe: examples\sundown.obj $(SUNDOWN_SRC)
- $(CC) examples\sundown.obj $(SUNDOWN_SRC) /link $(LDFLAGS) /out:$@
-
-# housekeeping
-clean:
- del $(SUNDOWN_SRC)
- del sundown.dll sundown.exe
- del sundown.exp sundown.lib
-
-# generic object compilations
-
-.c.obj:
- $(CC) $(CFLAGS) /c $< /Fo$@
-
+++ /dev/null
-Sundown
-=======
-
-`Sundown` is a Markdown parser based on the original code of the
-[Upskirt library](http://fossil.instinctive.eu/libupskirt/index) by Natacha Porté.
-
-Features
---------
-
-* **Fully standards compliant**
-
- `Sundown` passes out of the box the official Markdown v1.0.0 and v1.0.3
- test suites, and has been extensively tested with additional corner cases
- to make sure its output is as sane as possible at all times.
-
-* **Massive extension support**
-
- `Sundown` has optional support for several (unofficial) Markdown extensions,
- such as non-strict emphasis, fenced code blocks, tables, autolinks,
- strikethrough and more.
-
-* **UTF-8 aware**
-
- `Sundown` is fully UTF-8 aware, both when parsing the source document and when
- generating the resulting (X)HTML code.
-
-* **Tested & Ready to be used on production**
-
- `Sundown` has been extensively security audited, and includes protection against
- all possible DOS attacks (stack overflows, out of memory situations, malformed
- Markdown syntax...) and against client attacks through malicious embedded HTML.
-
- We've worked very hard to make `Sundown` never crash or run out of memory
- under *any* input. `Sundown` renders all the Markdown content in GitHub and so
- far hasn't crashed a single time.
-
-* **Customizable renderers**
-
- `Sundown` is not stuck with XHTML output: the Markdown parser of the library
- is decoupled from the renderer, so it's trivial to extend the library with
- custom renderers. A fully functional (X)HTML renderer is included.
-
-* **Optimized for speed**
-
- `Sundown` is written in C, with a special emphasis on performance. When wrapped
- on a dynamic language such as Python or Ruby, it has shown to be up to 40
- times faster than other native alternatives.
-
-* **Zero-dependency**
-
- `Sundown` is a zero-dependency library composed of 3 `.c` files and their headers.
- No dependencies, no bullshit. Only standard C99 that builds everywhere.
-
-Credits
--------
-
-`Sundown` is based on the original Upskirt parser by Natacha Porté, with many additions
-by Vicent Marti (@vmg) and contributions from the following authors:
-
- Ben Noordhuis, Bruno Michel, Joseph Koshy, Krzysztof Kowalczyk, Samuel Bronson,
- Shuhei Tanuma
-
-Bindings
---------
-
-`Sundown` is available from other programming languages thanks to these bindings developed
-by our awesome contributors.
-
-- [Redcarpet](https://github.com/vmg/redcarpet) (Ruby)
-- [RobotSkirt](https://github.com/benmills/robotskirt) (Node.js)
-- [Misaka](https://github.com/FSX/misaka) (Python)
-- [ffi-sundown](https://github.com/postmodern/ffi-sundown) (Ruby FFI)
-- [Sundown HS](https://github.com/bitonic/sundown) (Haskell)
-- [Goskirt](https://github.com/madari/goskirt) (Go)
-- [Upskirt.go](https://github.com/buu700/upskirt.go) (Go)
-- [MoonShine](https://github.com/brandonc/moonshine) (.NET)
-- [PHP-Sundown](https://github.com/chobie/php-sundown) (PHP)
-- [Sundown.net](https://github.com/txdv/sundown.net) (.NET)
-
-Help us
--------
-
-`Sundown` is all about security. If you find a (potential) security vulnerability in the
-library, or a way to make it crash through malicious input, please report it to us,
-either directly via email or by opening an Issue on GitHub, and help make the web safer
-for everybody.
-
-Unicode character handling
---------------------------
-
-Given that the Markdown spec makes no provision for Unicode character handling, `Sundown`
-takes a conservative approach towards deciding which extended characters trigger Markdown
-features:
-
-* Punctuation characters outside of the U+007F codepoint are not handled as punctuation.
- They are considered as normal, in-word characters for word-boundary checks.
-
-* Whitespace characters outside of the U+007F codepoint are not considered as
- whitespace. They are considered as normal, in-word characters for word-boundary checks.
-
-Install
--------
-
-There is nothing to install. `Sundown` is composed of 3 `.c` files (`markdown.c`,
-`buffer.c` and `array.c`), so just throw them in your project. Zero-dependency means
-zero-dependency. You might want to include `render/html.c` if you want to use the
-included XHTML renderer, or write your own renderer. Either way, it's all fun and joy.
-
-If you are hardcore, you can use the included `Makefile` to build `Sundown` into a dynamic
-library, or to build the sample `sundown` executable, which is just a commandline
-Markdown to XHTML parser. (If gcc gives you grief about `-fPIC`, e.g. with MinGW, try
-`make MFLAGS=` instead of just `make`.)
-
-License
--------
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-<!-- Local Variables: -->
-<!-- fill-column: 89 -->
-<!-- End: -->
+++ /dev/null
-/*
- * Copyright (c) 2011, Vicent Marti
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "markdown.h"
-#include "html.h"
-#include "buffer.h"
-
-#include <errno.h>
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define READ_UNIT 1024
-#define OUTPUT_UNIT 64
-
-int
-main(int argc, char **argv)
-{
- struct buf *ib, *ob;
- size_t ret;
- FILE *in = stdin;
-
- /* opening the file if given from the command line */
- if (argc > 1) {
- in = fopen(argv[1], "r");
- if (!in) {
- fprintf(stderr, "Unable to open input file \"%s\": %s\n", argv[0], strerror(errno));
- return 1;
- }
- }
-
- /* reading everything */
- ib = bufnew(READ_UNIT);
- bufgrow(ib, READ_UNIT);
- while ((ret = fread(ib->data + ib->size, 1, ib->asize - ib->size, in)) > 0) {
- ib->size += ret;
- bufgrow(ib, ib->size + READ_UNIT);
- }
-
- if (in != stdin)
- fclose(in);
-
- /* performing markdown parsing */
- ob = bufnew(OUTPUT_UNIT);
-
- sdhtml_smartypants(ob, ib->data, ib->size);
-
- /* writing the result to stdout */
- (void)fwrite(ob->data, 1, ob->size, stdout);
-
- /* cleanup */
- bufrelease(ib);
- bufrelease(ob);
-
- return 0;
-}
-
-/* vim: set filetype=c: */
+++ /dev/null
-/*
- * Copyright (c) 2011, Vicent Marti
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "markdown.h"
-#include "html.h"
-#include "buffer.h"
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define READ_UNIT 1024
-#define OUTPUT_UNIT 64
-
-/* main • main function, interfacing STDIO with the parser */
-int
-main(int argc, char **argv)
-{
- struct buf *ib, *ob;
- int ret;
- FILE *in = stdin;
-
- struct sd_callbacks callbacks;
- struct html_renderopt options;
- struct sd_markdown *markdown;
-
- /* opening the file if given from the command line */
- if (argc > 1) {
- in = fopen(argv[1], "r");
- if (!in) {
- fprintf(stderr,"Unable to open input file \"%s\": %s\n", argv[1], strerror(errno));
- return 1;
- }
- }
-
- /* reading everything */
- ib = bufnew(READ_UNIT);
- bufgrow(ib, READ_UNIT);
- while ((ret = fread(ib->data + ib->size, 1, ib->asize - ib->size, in)) > 0) {
- ib->size += ret;
- bufgrow(ib, ib->size + READ_UNIT);
- }
-
- if (in != stdin)
- fclose(in);
-
- /* performing markdown parsing */
- ob = bufnew(OUTPUT_UNIT);
-
- sdhtml_renderer(&callbacks, &options, 0);
- markdown = sd_markdown_new(0, 16, &callbacks, &options);
-
- sd_markdown_render(ob, ib->data, ib->size, markdown);
- sd_markdown_free(markdown);
-
- /* writing the result to stdout */
- ret = fwrite(ob->data, 1, ob->size, stdout);
-
- /* cleanup */
- bufrelease(ib);
- bufrelease(ob);
-
- return (ret < 0) ? -1 : 0;
-}
-
-/* vim: set filetype=c: */
+++ /dev/null
-#ifndef HOUDINI_H__
-#define HOUDINI_H__
-
-#include "buffer.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef HOUDINI_USE_LOCALE
-# define _isxdigit(c) isxdigit(c)
-# define _isdigit(c) isdigit(c)
-#else
-/*
- * Helper _isdigit methods -- do not trust the current locale
- * */
-# define _isxdigit(c) (strchr("0123456789ABCDEFabcdef", (c)) != NULL)
-# define _isdigit(c) ((c) >= '0' && (c) <= '9')
-#endif
-
-extern void houdini_escape_html(struct buf *ob, const uint8_t *src, size_t size);
-extern void houdini_escape_html0(struct buf *ob, const uint8_t *src, size_t size, int secure);
-extern void houdini_unescape_html(struct buf *ob, const uint8_t *src, size_t size);
-extern void houdini_escape_xml(struct buf *ob, const uint8_t *src, size_t size);
-extern void houdini_escape_uri(struct buf *ob, const uint8_t *src, size_t size);
-extern void houdini_escape_url(struct buf *ob, const uint8_t *src, size_t size);
-extern void houdini_escape_href(struct buf *ob, const uint8_t *src, size_t size);
-extern void houdini_unescape_uri(struct buf *ob, const uint8_t *src, size_t size);
-extern void houdini_unescape_url(struct buf *ob, const uint8_t *src, size_t size);
-extern void houdini_escape_js(struct buf *ob, const uint8_t *src, size_t size);
-extern void houdini_unescape_js(struct buf *ob, const uint8_t *src, size_t size);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "houdini.h"
-
-#define ESCAPE_GROW_FACTOR(x) (((x) * 12) / 10)
-
-/*
- * The following characters will not be escaped:
- *
- * -_.+!*'(),%#@?=;:/,+&$ alphanum
- *
- * Note that this character set is the addition of:
- *
- * - The characters which are safe to be in an URL
- * - The characters which are *not* safe to be in
- * an URL because they are RESERVED characters.
- *
- * We asume (lazily) that any RESERVED char that
- * appears inside an URL is actually meant to
- * have its native function (i.e. as an URL
- * component/separator) and hence needs no escaping.
- *
- * There are two exceptions: the chacters & (amp)
- * and ' (single quote) do not appear in the table.
- * They are meant to appear in the URL as components,
- * yet they require special HTML-entity escaping
- * to generate valid HTML markup.
- *
- * All other characters will be escaped to %XX.
- *
- */
-static const char HREF_SAFE[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-void
-houdini_escape_href(struct buf *ob, const uint8_t *src, size_t size)
-{
- static const char hex_chars[] = "0123456789ABCDEF";
- size_t i = 0, org;
- char hex_str[3];
-
- bufgrow(ob, ESCAPE_GROW_FACTOR(size));
- hex_str[0] = '%';
-
- while (i < size) {
- org = i;
- while (i < size && HREF_SAFE[src[i]] != 0)
- i++;
-
- if (i > org)
- bufput(ob, src + org, i - org);
-
- /* escaping */
- if (i >= size)
- break;
-
- switch (src[i]) {
- /* amp appears all the time in URLs, but needs
- * HTML-entity escaping to be inside an href */
- case '&':
- BUFPUTSL(ob, "&");
- break;
-
- /* the single quote is a valid URL character
- * according to the standard; it needs HTML
- * entity escaping too */
- case '\'':
- BUFPUTSL(ob, "'");
- break;
-
- /* the space can be escaped to %20 or a plus
- * sign. we're going with the generic escape
- * for now. the plus thing is more commonly seen
- * when building GET strings */
-#if 0
- case ' ':
- bufputc(ob, '+');
- break;
-#endif
-
- /* every other character goes with a %XX escaping */
- default:
- hex_str[1] = hex_chars[(src[i] >> 4) & 0xF];
- hex_str[2] = hex_chars[src[i] & 0xF];
- bufput(ob, hex_str, 3);
- }
-
- i++;
- }
-}
+++ /dev/null
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "houdini.h"
-
-#define ESCAPE_GROW_FACTOR(x) (((x) * 12) / 10) /* this is very scientific, yes */
-
-/**
- * According to the OWASP rules:
- *
- * & --> &
- * < --> <
- * > --> >
- * " --> "
- * ' --> ' ' is not recommended
- * / --> / forward slash is included as it helps end an HTML entity
- *
- */
-static const char HTML_ESCAPE_TABLE[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-static const char *HTML_ESCAPES[] = {
- "",
- """,
- "&",
- "'",
- "/",
- "<",
- ">"
-};
-
-void
-houdini_escape_html0(struct buf *ob, const uint8_t *src, size_t size, int secure)
-{
- size_t i = 0, org, esc = 0;
-
- bufgrow(ob, ESCAPE_GROW_FACTOR(size));
-
- while (i < size) {
- org = i;
- while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0)
- i++;
-
- if (i > org)
- bufput(ob, src + org, i - org);
-
- /* escaping */
- if (i >= size)
- break;
-
- /* The forward slash is only escaped in secure mode */
- if (src[i] == '/' && !secure) {
- bufputc(ob, '/');
- } else {
- bufputs(ob, HTML_ESCAPES[esc]);
- }
-
- i++;
- }
-}
-
-void
-houdini_escape_html(struct buf *ob, const uint8_t *src, size_t size)
-{
- houdini_escape_html0(ob, src, size, 1);
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2009, Natacha Porté
- * Copyright (c) 2011, Vicent Marti
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "markdown.h"
-#include "html.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#include "houdini.h"
-
-#define USE_XHTML(opt) (opt->flags & HTML_USE_XHTML)
-
-int
-sdhtml_is_tag(const uint8_t *tag_data, size_t tag_size, const char *tagname)
-{
- size_t i;
- int closed = 0;
-
- if (tag_size < 3 || tag_data[0] != '<')
- return HTML_TAG_NONE;
-
- i = 1;
-
- if (tag_data[i] == '/') {
- closed = 1;
- i++;
- }
-
- for (; i < tag_size; ++i, ++tagname) {
- if (*tagname == 0)
- break;
-
- if (tag_data[i] != *tagname)
- return HTML_TAG_NONE;
- }
-
- if (i == tag_size)
- return HTML_TAG_NONE;
-
- if (isspace(tag_data[i]) || tag_data[i] == '>')
- return closed ? HTML_TAG_CLOSE : HTML_TAG_OPEN;
-
- return HTML_TAG_NONE;
-}
-
-static inline void escape_html(struct buf *ob, const uint8_t *source, size_t length)
-{
- houdini_escape_html0(ob, source, length, 0);
-}
-
-static inline void escape_href(struct buf *ob, const uint8_t *source, size_t length)
-{
- houdini_escape_href(ob, source, length);
-}
-
-/********************
- * GENERIC RENDERER *
- ********************/
-static int
-rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type, void *opaque)
-{
- struct html_renderopt *options = opaque;
-
- if (!link || !link->size)
- return 0;
-
- if ((options->flags & HTML_SAFELINK) != 0 &&
- !sd_autolink_issafe(link->data, link->size) &&
- type != MKDA_EMAIL)
- return 0;
-
- BUFPUTSL(ob, "<a href=\"");
- if (type == MKDA_EMAIL)
- BUFPUTSL(ob, "mailto:");
- escape_href(ob, link->data, link->size);
-
- if (options->link_attributes) {
- bufputc(ob, '\"');
- options->link_attributes(ob, link, opaque);
- bufputc(ob, '>');
- } else {
- BUFPUTSL(ob, "\">");
- }
-
- /*
- * Pretty printing: if we get an email address as
- * an actual URI, e.g. `mailto:foo@bar.com`, we don't
- * want to print the `mailto:` prefix
- */
- if (bufprefix(link, "mailto:") == 0) {
- escape_html(ob, link->data + 7, link->size - 7);
- } else {
- escape_html(ob, link->data, link->size);
- }
-
- BUFPUTSL(ob, "</a>");
-
- return 1;
-}
-
-static void
-rndr_blockcode(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque)
-{
- if (ob->size) bufputc(ob, '\n');
-
- if (lang && lang->size) {
- size_t i, cls;
- BUFPUTSL(ob, "<pre><code class=\"");
-
- for (i = 0, cls = 0; i < lang->size; ++i, ++cls) {
- while (i < lang->size && isspace(lang->data[i]))
- i++;
-
- if (i < lang->size) {
- size_t org = i;
- while (i < lang->size && !isspace(lang->data[i]))
- i++;
-
- if (lang->data[org] == '.')
- org++;
-
- if (cls) bufputc(ob, ' ');
- escape_html(ob, lang->data + org, i - org);
- }
- }
-
- BUFPUTSL(ob, "\">");
- } else
- BUFPUTSL(ob, "<pre><code>");
-
- if (text)
- escape_html(ob, text->data, text->size);
-
- BUFPUTSL(ob, "</code></pre>\n");
-}
-
-static void
-rndr_blockquote(struct buf *ob, const struct buf *text, void *opaque)
-{
- if (ob->size) bufputc(ob, '\n');
- BUFPUTSL(ob, "<blockquote>\n");
- if (text) bufput(ob, text->data, text->size);
- BUFPUTSL(ob, "</blockquote>\n");
-}
-
-static int
-rndr_codespan(struct buf *ob, const struct buf *text, void *opaque)
-{
- BUFPUTSL(ob, "<code>");
- if (text) escape_html(ob, text->data, text->size);
- BUFPUTSL(ob, "</code>");
- return 1;
-}
-
-static int
-rndr_strikethrough(struct buf *ob, const struct buf *text, void *opaque)
-{
- if (!text || !text->size)
- return 0;
-
- BUFPUTSL(ob, "<del>");
- bufput(ob, text->data, text->size);
- BUFPUTSL(ob, "</del>");
- return 1;
-}
-
-static int
-rndr_double_emphasis(struct buf *ob, const struct buf *text, void *opaque)
-{
- if (!text || !text->size)
- return 0;
-
- BUFPUTSL(ob, "<strong>");
- bufput(ob, text->data, text->size);
- BUFPUTSL(ob, "</strong>");
-
- return 1;
-}
-
-static int
-rndr_emphasis(struct buf *ob, const struct buf *text, void *opaque)
-{
- if (!text || !text->size) return 0;
- BUFPUTSL(ob, "<em>");
- if (text) bufput(ob, text->data, text->size);
- BUFPUTSL(ob, "</em>");
- return 1;
-}
-
-static int
-rndr_linebreak(struct buf *ob, void *opaque)
-{
- struct html_renderopt *options = opaque;
- bufputs(ob, USE_XHTML(options) ? "<br/>\n" : "<br>\n");
- return 1;
-}
-
-static void
-rndr_header(struct buf *ob, const struct buf *text, int level, void *opaque)
-{
- struct html_renderopt *options = opaque;
-
- if (ob->size)
- bufputc(ob, '\n');
-
- if (options->flags & HTML_TOC)
- bufprintf(ob, "<h%d id=\"toc_%d\">", level, options->toc_data.header_count++);
- else
- bufprintf(ob, "<h%d>", level);
-
- if (text) bufput(ob, text->data, text->size);
- bufprintf(ob, "</h%d>\n", level);
-}
-
-static int
-rndr_link(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque)
-{
- struct html_renderopt *options = opaque;
-
- if (link != NULL && (options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size))
- return 0;
-
- BUFPUTSL(ob, "<a href=\"");
-
- if (link && link->size)
- escape_href(ob, link->data, link->size);
-
- if (title && title->size) {
- BUFPUTSL(ob, "\" title=\"");
- escape_html(ob, title->data, title->size);
- }
-
- if (options->link_attributes) {
- bufputc(ob, '\"');
- options->link_attributes(ob, link, opaque);
- bufputc(ob, '>');
- } else {
- BUFPUTSL(ob, "\">");
- }
-
- if (content && content->size) bufput(ob, content->data, content->size);
- BUFPUTSL(ob, "</a>");
- return 1;
-}
-
-static void
-rndr_list(struct buf *ob, const struct buf *text, int flags, void *opaque)
-{
- if (ob->size) bufputc(ob, '\n');
- bufput(ob, flags & MKD_LIST_ORDERED ? "<ol>\n" : "<ul>\n", 5);
- if (text) bufput(ob, text->data, text->size);
- bufput(ob, flags & MKD_LIST_ORDERED ? "</ol>\n" : "</ul>\n", 6);
-}
-
-static void
-rndr_listitem(struct buf *ob, const struct buf *text, int flags, void *opaque)
-{
- BUFPUTSL(ob, "<li>");
- if (text) {
- size_t size = text->size;
- while (size && text->data[size - 1] == '\n')
- size--;
-
- bufput(ob, text->data, size);
- }
- BUFPUTSL(ob, "</li>\n");
-}
-
-static void
-rndr_paragraph(struct buf *ob, const struct buf *text, void *opaque)
-{
- struct html_renderopt *options = opaque;
- size_t i = 0;
-
- if (ob->size) bufputc(ob, '\n');
-
- if (!text || !text->size)
- return;
-
- while (i < text->size && isspace(text->data[i])) i++;
-
- if (i == text->size)
- return;
-
- BUFPUTSL(ob, "<p>");
- if (options->flags & HTML_HARD_WRAP) {
- size_t org;
- while (i < text->size) {
- org = i;
- while (i < text->size && text->data[i] != '\n')
- i++;
-
- if (i > org)
- bufput(ob, text->data + org, i - org);
-
- /*
- * do not insert a line break if this newline
- * is the last character on the paragraph
- */
- if (i >= text->size - 1)
- break;
-
- rndr_linebreak(ob, opaque);
- i++;
- }
- } else {
- bufput(ob, &text->data[i], text->size - i);
- }
- BUFPUTSL(ob, "</p>\n");
-}
-
-static void
-rndr_raw_block(struct buf *ob, const struct buf *text, void *opaque)
-{
- size_t org, sz;
- if (!text) return;
- sz = text->size;
- while (sz > 0 && text->data[sz - 1] == '\n') sz--;
- org = 0;
- while (org < sz && text->data[org] == '\n') org++;
- if (org >= sz) return;
- if (ob->size) bufputc(ob, '\n');
- bufput(ob, text->data + org, sz - org);
- bufputc(ob, '\n');
-}
-
-static int
-rndr_triple_emphasis(struct buf *ob, const struct buf *text, void *opaque)
-{
- if (!text || !text->size) return 0;
- BUFPUTSL(ob, "<strong><em>");
- bufput(ob, text->data, text->size);
- BUFPUTSL(ob, "</em></strong>");
- return 1;
-}
-
-static void
-rndr_hrule(struct buf *ob, void *opaque)
-{
- struct html_renderopt *options = opaque;
- if (ob->size) bufputc(ob, '\n');
- bufputs(ob, USE_XHTML(options) ? "<hr/>\n" : "<hr>\n");
-}
-
-static int
-rndr_image(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque)
-{
- struct html_renderopt *options = opaque;
- if (!link || !link->size) return 0;
-
- BUFPUTSL(ob, "<img src=\"");
- escape_href(ob, link->data, link->size);
- BUFPUTSL(ob, "\" alt=\"");
-
- if (alt && alt->size)
- escape_html(ob, alt->data, alt->size);
-
- if (title && title->size) {
- BUFPUTSL(ob, "\" title=\"");
- escape_html(ob, title->data, title->size); }
-
- bufputs(ob, USE_XHTML(options) ? "\"/>" : "\">");
- return 1;
-}
-
-static int
-rndr_raw_html(struct buf *ob, const struct buf *text, void *opaque)
-{
- struct html_renderopt *options = opaque;
-
- /* HTML_ESCAPE overrides SKIP_HTML, SKIP_STYLE, SKIP_LINKS and SKIP_IMAGES
- * It doens't see if there are any valid tags, just escape all of them. */
- if((options->flags & HTML_ESCAPE) != 0) {
- escape_html(ob, text->data, text->size);
- return 1;
- }
-
- if ((options->flags & HTML_SKIP_HTML) != 0)
- return 1;
-
- if ((options->flags & HTML_SKIP_STYLE) != 0 &&
- sdhtml_is_tag(text->data, text->size, "style"))
- return 1;
-
- if ((options->flags & HTML_SKIP_LINKS) != 0 &&
- sdhtml_is_tag(text->data, text->size, "a"))
- return 1;
-
- if ((options->flags & HTML_SKIP_IMAGES) != 0 &&
- sdhtml_is_tag(text->data, text->size, "img"))
- return 1;
-
- bufput(ob, text->data, text->size);
- return 1;
-}
-
-static void
-rndr_table(struct buf *ob, const struct buf *header, const struct buf *body, void *opaque)
-{
- if (ob->size) bufputc(ob, '\n');
- BUFPUTSL(ob, "<table><thead>\n");
- if (header)
- bufput(ob, header->data, header->size);
- BUFPUTSL(ob, "</thead><tbody>\n");
- if (body)
- bufput(ob, body->data, body->size);
- BUFPUTSL(ob, "</tbody></table>\n");
-}
-
-static void
-rndr_tablerow(struct buf *ob, const struct buf *text, void *opaque)
-{
- BUFPUTSL(ob, "<tr>\n");
- if (text)
- bufput(ob, text->data, text->size);
- BUFPUTSL(ob, "</tr>\n");
-}
-
-static void
-rndr_tablecell(struct buf *ob, const struct buf *text, int flags, void *opaque)
-{
- if (flags & MKD_TABLE_HEADER) {
- BUFPUTSL(ob, "<th");
- } else {
- BUFPUTSL(ob, "<td");
- }
-
- switch (flags & MKD_TABLE_ALIGNMASK) {
- case MKD_TABLE_ALIGN_CENTER:
- BUFPUTSL(ob, " align=\"center\">");
- break;
-
- case MKD_TABLE_ALIGN_L:
- BUFPUTSL(ob, " align=\"left\">");
- break;
-
- case MKD_TABLE_ALIGN_R:
- BUFPUTSL(ob, " align=\"right\">");
- break;
-
- default:
- BUFPUTSL(ob, ">");
- }
-
- if (text)
- bufput(ob, text->data, text->size);
-
- if (flags & MKD_TABLE_HEADER) {
- BUFPUTSL(ob, "</th>\n");
- } else {
- BUFPUTSL(ob, "</td>\n");
- }
-}
-
-static int
-rndr_superscript(struct buf *ob, const struct buf *text, void *opaque)
-{
- if (!text || !text->size) return 0;
- BUFPUTSL(ob, "<sup>");
- bufput(ob, text->data, text->size);
- BUFPUTSL(ob, "</sup>");
- return 1;
-}
-
-static void
-rndr_normal_text(struct buf *ob, const struct buf *text, void *opaque)
-{
- if (text)
- escape_html(ob, text->data, text->size);
-}
-
-static void
-toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
-{
- struct html_renderopt *options = opaque;
-
- /* set the level offset if this is the first header
- * we're parsing for the document */
- if (options->toc_data.current_level == 0) {
- options->toc_data.level_offset = level - 1;
- }
- level -= options->toc_data.level_offset;
-
- if (level > options->toc_data.current_level) {
- while (level > options->toc_data.current_level) {
- BUFPUTSL(ob, "<ul>\n<li>\n");
- options->toc_data.current_level++;
- }
- } else if (level < options->toc_data.current_level) {
- BUFPUTSL(ob, "</li>\n");
- while (level < options->toc_data.current_level) {
- BUFPUTSL(ob, "</ul>\n</li>\n");
- options->toc_data.current_level--;
- }
- BUFPUTSL(ob,"<li>\n");
- } else {
- BUFPUTSL(ob,"</li>\n<li>\n");
- }
-
- bufprintf(ob, "<a href=\"#toc_%d\">", options->toc_data.header_count++);
- if (text)
- escape_html(ob, text->data, text->size);
- BUFPUTSL(ob, "</a>\n");
-}
-
-static int
-toc_link(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque)
-{
- if (content && content->size)
- bufput(ob, content->data, content->size);
- return 1;
-}
-
-static void
-toc_finalize(struct buf *ob, void *opaque)
-{
- struct html_renderopt *options = opaque;
-
- while (options->toc_data.current_level > 0) {
- BUFPUTSL(ob, "</li>\n</ul>\n");
- options->toc_data.current_level--;
- }
-}
-
-void
-sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options)
-{
- static const struct sd_callbacks cb_default = {
- NULL,
- NULL,
- NULL,
- toc_header,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
-
- NULL,
- rndr_codespan,
- rndr_double_emphasis,
- rndr_emphasis,
- NULL,
- NULL,
- toc_link,
- NULL,
- rndr_triple_emphasis,
- rndr_strikethrough,
- rndr_superscript,
-
- NULL,
- NULL,
-
- NULL,
- toc_finalize,
- };
-
- memset(options, 0x0, sizeof(struct html_renderopt));
- options->flags = HTML_TOC;
-
- memcpy(callbacks, &cb_default, sizeof(struct sd_callbacks));
-}
-
-void
-sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options, unsigned int render_flags)
-{
- static const struct sd_callbacks cb_default = {
- rndr_blockcode,
- rndr_blockquote,
- rndr_raw_block,
- rndr_header,
- rndr_hrule,
- rndr_list,
- rndr_listitem,
- rndr_paragraph,
- rndr_table,
- rndr_tablerow,
- rndr_tablecell,
-
- rndr_autolink,
- rndr_codespan,
- rndr_double_emphasis,
- rndr_emphasis,
- rndr_image,
- rndr_linebreak,
- rndr_link,
- rndr_raw_html,
- rndr_triple_emphasis,
- rndr_strikethrough,
- rndr_superscript,
-
- NULL,
- rndr_normal_text,
-
- NULL,
- NULL,
- };
-
- /* Prepare the options pointer */
- memset(options, 0x0, sizeof(struct html_renderopt));
- options->flags = render_flags;
-
- /* Prepare the callbacks */
- memcpy(callbacks, &cb_default, sizeof(struct sd_callbacks));
-
- if (render_flags & HTML_SKIP_IMAGES)
- callbacks->image = NULL;
-
- if (render_flags & HTML_SKIP_LINKS) {
- callbacks->link = NULL;
- callbacks->autolink = NULL;
- }
-
- if (render_flags & HTML_SKIP_HTML || render_flags & HTML_ESCAPE)
- callbacks->blockhtml = NULL;
-}
+++ /dev/null
-/*
- * Copyright (c) 2011, Vicent Marti
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef UPSKIRT_HTML_H
-#define UPSKIRT_HTML_H
-
-#include "markdown.h"
-#include "buffer.h"
-#include <stdlib.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct html_renderopt {
- struct {
- int header_count;
- int current_level;
- int level_offset;
- } toc_data;
-
- unsigned int flags;
-
- /* extra callbacks */
- void (*link_attributes)(struct buf *ob, const struct buf *url, void *self);
-};
-
-typedef enum {
- HTML_SKIP_HTML = (1 << 0),
- HTML_SKIP_STYLE = (1 << 1),
- HTML_SKIP_IMAGES = (1 << 2),
- HTML_SKIP_LINKS = (1 << 3),
- HTML_EXPAND_TABS = (1 << 4),
- HTML_SAFELINK = (1 << 5),
- HTML_TOC = (1 << 6),
- HTML_HARD_WRAP = (1 << 7),
- HTML_USE_XHTML = (1 << 8),
- HTML_ESCAPE = (1 << 9),
-} html_render_mode;
-
-typedef enum {
- HTML_TAG_NONE = 0,
- HTML_TAG_OPEN,
- HTML_TAG_CLOSE,
-} html_tag;
-
-int
-sdhtml_is_tag(const uint8_t *tag_data, size_t tag_size, const char *tagname);
-
-extern void
-sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr, unsigned int render_flags);
-
-extern void
-sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr);
-
-extern void
-sdhtml_smartypants(struct buf *ob, const uint8_t *text, size_t size);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
+++ /dev/null
-/*
- * Copyright (c) 2011, Vicent Marti
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "buffer.h"
-#include "html.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#if defined(_WIN32)
-#define snprintf _snprintf
-#endif
-
-struct smartypants_data {
- int in_squote;
- int in_dquote;
-};
-
-static size_t smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
-static size_t smartypants_cb__dquote(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
-static size_t smartypants_cb__amp(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
-static size_t smartypants_cb__period(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
-static size_t smartypants_cb__number(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
-static size_t smartypants_cb__dash(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
-static size_t smartypants_cb__parens(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
-static size_t smartypants_cb__squote(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
-static size_t smartypants_cb__backtick(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
-static size_t smartypants_cb__escape(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size);
-
-static size_t (*smartypants_cb_ptrs[])
- (struct buf *, struct smartypants_data *, uint8_t, const uint8_t *, size_t) =
-{
- NULL, /* 0 */
- smartypants_cb__dash, /* 1 */
- smartypants_cb__parens, /* 2 */
- smartypants_cb__squote, /* 3 */
- smartypants_cb__dquote, /* 4 */
- smartypants_cb__amp, /* 5 */
- smartypants_cb__period, /* 6 */
- smartypants_cb__number, /* 7 */
- smartypants_cb__ltag, /* 8 */
- smartypants_cb__backtick, /* 9 */
- smartypants_cb__escape, /* 10 */
-};
-
-static const uint8_t smartypants_cb_chars[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 4, 0, 0, 0, 5, 3, 2, 0, 0, 0, 0, 1, 6, 0,
- 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0,
- 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-static inline int
-word_boundary(uint8_t c)
-{
- return c == 0 || isspace(c) || ispunct(c);
-}
-
-static int
-smartypants_quotes(struct buf *ob, uint8_t previous_char, uint8_t next_char, uint8_t quote, int *is_open)
-{
- char ent[8];
-
- if (*is_open && !word_boundary(next_char))
- return 0;
-
- if (!(*is_open) && !word_boundary(previous_char))
- return 0;
-
- snprintf(ent, sizeof(ent), "&%c%cquo;", (*is_open) ? 'r' : 'l', quote);
- *is_open = !(*is_open);
- bufputs(ob, ent);
- return 1;
-}
-
-static size_t
-smartypants_cb__squote(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
-{
- if (size >= 2) {
- uint8_t t1 = tolower(text[1]);
-
- if (t1 == '\'') {
- if (smartypants_quotes(ob, previous_char, size >= 3 ? text[2] : 0, 'd', &smrt->in_dquote))
- return 1;
- }
-
- if ((t1 == 's' || t1 == 't' || t1 == 'm' || t1 == 'd') &&
- (size == 3 || word_boundary(text[2]))) {
- BUFPUTSL(ob, "’");
- return 0;
- }
-
- if (size >= 3) {
- uint8_t t2 = tolower(text[2]);
-
- if (((t1 == 'r' && t2 == 'e') ||
- (t1 == 'l' && t2 == 'l') ||
- (t1 == 'v' && t2 == 'e')) &&
- (size == 4 || word_boundary(text[3]))) {
- BUFPUTSL(ob, "’");
- return 0;
- }
- }
- }
-
- if (smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 's', &smrt->in_squote))
- return 0;
-
- bufputc(ob, text[0]);
- return 0;
-}
-
-static size_t
-smartypants_cb__parens(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
-{
- if (size >= 3) {
- uint8_t t1 = tolower(text[1]);
- uint8_t t2 = tolower(text[2]);
-
- if (t1 == 'c' && t2 == ')') {
- BUFPUTSL(ob, "©");
- return 2;
- }
-
- if (t1 == 'r' && t2 == ')') {
- BUFPUTSL(ob, "®");
- return 2;
- }
-
- if (size >= 4 && t1 == 't' && t2 == 'm' && text[3] == ')') {
- BUFPUTSL(ob, "™");
- return 3;
- }
- }
-
- bufputc(ob, text[0]);
- return 0;
-}
-
-static size_t
-smartypants_cb__dash(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
-{
- if (size >= 3 && text[1] == '-' && text[2] == '-') {
- BUFPUTSL(ob, "—");
- return 2;
- }
-
- if (size >= 2 && text[1] == '-') {
- BUFPUTSL(ob, "–");
- return 1;
- }
-
- bufputc(ob, text[0]);
- return 0;
-}
-
-static size_t
-smartypants_cb__amp(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
-{
- if (size >= 6 && memcmp(text, """, 6) == 0) {
- if (smartypants_quotes(ob, previous_char, size >= 7 ? text[6] : 0, 'd', &smrt->in_dquote))
- return 5;
- }
-
- if (size >= 4 && memcmp(text, "�", 4) == 0)
- return 3;
-
- bufputc(ob, '&');
- return 0;
-}
-
-static size_t
-smartypants_cb__period(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
-{
- if (size >= 3 && text[1] == '.' && text[2] == '.') {
- BUFPUTSL(ob, "…");
- return 2;
- }
-
- if (size >= 5 && text[1] == ' ' && text[2] == '.' && text[3] == ' ' && text[4] == '.') {
- BUFPUTSL(ob, "…");
- return 4;
- }
-
- bufputc(ob, text[0]);
- return 0;
-}
-
-static size_t
-smartypants_cb__backtick(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
-{
- if (size >= 2 && text[1] == '`') {
- if (smartypants_quotes(ob, previous_char, size >= 3 ? text[2] : 0, 'd', &smrt->in_dquote))
- return 1;
- }
-
- return 0;
-}
-
-static size_t
-smartypants_cb__number(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
-{
- if (word_boundary(previous_char) && size >= 3) {
- if (text[0] == '1' && text[1] == '/' && text[2] == '2') {
- if (size == 3 || word_boundary(text[3])) {
- BUFPUTSL(ob, "½");
- return 2;
- }
- }
-
- if (text[0] == '1' && text[1] == '/' && text[2] == '4') {
- if (size == 3 || word_boundary(text[3]) ||
- (size >= 5 && tolower(text[3]) == 't' && tolower(text[4]) == 'h')) {
- BUFPUTSL(ob, "¼");
- return 2;
- }
- }
-
- if (text[0] == '3' && text[1] == '/' && text[2] == '4') {
- if (size == 3 || word_boundary(text[3]) ||
- (size >= 6 && tolower(text[3]) == 't' && tolower(text[4]) == 'h' && tolower(text[5]) == 's')) {
- BUFPUTSL(ob, "¾");
- return 2;
- }
- }
- }
-
- bufputc(ob, text[0]);
- return 0;
-}
-
-static size_t
-smartypants_cb__dquote(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
-{
- if (!smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 'd', &smrt->in_dquote))
- BUFPUTSL(ob, """);
-
- return 0;
-}
-
-static size_t
-smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
-{
- static const char *skip_tags[] = {
- "pre", "code", "var", "samp", "kbd", "math", "script", "style"
- };
- static const size_t skip_tags_count = 8;
-
- size_t tag, i = 0;
-
- while (i < size && text[i] != '>')
- i++;
-
- for (tag = 0; tag < skip_tags_count; ++tag) {
- if (sdhtml_is_tag(text, size, skip_tags[tag]) == HTML_TAG_OPEN)
- break;
- }
-
- if (tag < skip_tags_count) {
- for (;;) {
- while (i < size && text[i] != '<')
- i++;
-
- if (i == size)
- break;
-
- if (sdhtml_is_tag(text + i, size - i, skip_tags[tag]) == HTML_TAG_CLOSE)
- break;
-
- i++;
- }
-
- while (i < size && text[i] != '>')
- i++;
- }
-
- bufput(ob, text, i + 1);
- return i;
-}
-
-static size_t
-smartypants_cb__escape(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
-{
- if (size < 2)
- return 0;
-
- switch (text[1]) {
- case '\\':
- case '"':
- case '\'':
- case '.':
- case '-':
- case '`':
- bufputc(ob, text[1]);
- return 1;
-
- default:
- bufputc(ob, '\\');
- return 0;
- }
-}
-
-#if 0
-static struct {
- uint8_t c0;
- const uint8_t *pattern;
- const uint8_t *entity;
- int skip;
-} smartypants_subs[] = {
- { '\'', "'s>", "’", 0 },
- { '\'', "'t>", "’", 0 },
- { '\'', "'re>", "’", 0 },
- { '\'', "'ll>", "’", 0 },
- { '\'', "'ve>", "’", 0 },
- { '\'', "'m>", "’", 0 },
- { '\'', "'d>", "’", 0 },
- { '-', "--", "—", 1 },
- { '-', "<->", "–", 0 },
- { '.', "...", "…", 2 },
- { '.', ". . .", "…", 4 },
- { '(', "(c)", "©", 2 },
- { '(', "(r)", "®", 2 },
- { '(', "(tm)", "™", 3 },
- { '3', "<3/4>", "¾", 2 },
- { '3', "<3/4ths>", "¾", 2 },
- { '1', "<1/2>", "½", 2 },
- { '1', "<1/4>", "¼", 2 },
- { '1', "<1/4th>", "¼", 2 },
- { '&', "�", 0, 3 },
-};
-#endif
-
-void
-sdhtml_smartypants(struct buf *ob, const uint8_t *text, size_t size)
-{
- size_t i;
- struct smartypants_data smrt = {0, 0};
-
- if (!text)
- return;
-
- bufgrow(ob, size);
-
- for (i = 0; i < size; ++i) {
- size_t org;
- uint8_t action = 0;
-
- org = i;
- while (i < size && (action = smartypants_cb_chars[text[i]]) == 0)
- i++;
-
- if (i > org)
- bufput(ob, text + org, i - org);
-
- if (i < size) {
- i += smartypants_cb_ptrs[(int)action]
- (ob, &smrt, i ? text[i - 1] : 0, text + i, size - i);
- }
- }
-}
-
-
+++ /dev/null
-##
-p
-dl
-h1
-h2
-h3
-h4
-h5
-h6
-ol
-ul
-del
-div
-ins
-pre
-form
-math
-table
-figure
-iframe
-script
-style
-fieldset
-noscript
-blockquote
+++ /dev/null
-/*
- * Copyright (c) 2011, Vicent Marti
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "buffer.h"
-#include "autolink.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#if defined(_WIN32)
-#define strncasecmp _strnicmp
-#endif
-
-int
-sd_autolink_issafe(const uint8_t *link, size_t link_len)
-{
- static const size_t valid_uris_count = 5;
- static const char *valid_uris[] = {
- "/", "http://", "https://", "ftp://", "mailto:"
- };
-
- size_t i;
-
- for (i = 0; i < valid_uris_count; ++i) {
- size_t len = strlen(valid_uris[i]);
-
- if (link_len > len &&
- strncasecmp((char *)link, valid_uris[i], len) == 0 &&
- isalnum(link[len]))
- return 1;
- }
-
- return 0;
-}
-
-static size_t
-autolink_delim(uint8_t *data, size_t link_end, size_t max_rewind, size_t size)
-{
- uint8_t cclose, copen = 0;
- size_t i;
-
- for (i = 0; i < link_end; ++i)
- if (data[i] == '<') {
- link_end = i;
- break;
- }
-
- while (link_end > 0) {
- if (strchr("?!.,", data[link_end - 1]) != NULL)
- link_end--;
-
- else if (data[link_end - 1] == ';') {
- size_t new_end = link_end - 2;
-
- while (new_end > 0 && isalpha(data[new_end]))
- new_end--;
-
- if (new_end < link_end - 2 && data[new_end] == '&')
- link_end = new_end;
- else
- link_end--;
- }
- else break;
- }
-
- if (link_end == 0)
- return 0;
-
- cclose = data[link_end - 1];
-
- switch (cclose) {
- case '"': copen = '"'; break;
- case '\'': copen = '\''; break;
- case ')': copen = '('; break;
- case ']': copen = '['; break;
- case '}': copen = '{'; break;
- }
-
- if (copen != 0) {
- size_t closing = 0;
- size_t opening = 0;
- size_t i = 0;
-
- /* Try to close the final punctuation sign in this same line;
- * if we managed to close it outside of the URL, that means that it's
- * not part of the URL. If it closes inside the URL, that means it
- * is part of the URL.
- *
- * Examples:
- *
- * foo http://www.pokemon.com/Pikachu_(Electric) bar
- * => http://www.pokemon.com/Pikachu_(Electric)
- *
- * foo (http://www.pokemon.com/Pikachu_(Electric)) bar
- * => http://www.pokemon.com/Pikachu_(Electric)
- *
- * foo http://www.pokemon.com/Pikachu_(Electric)) bar
- * => http://www.pokemon.com/Pikachu_(Electric))
- *
- * (foo http://www.pokemon.com/Pikachu_(Electric)) bar
- * => foo http://www.pokemon.com/Pikachu_(Electric)
- */
-
- while (i < link_end) {
- if (data[i] == copen)
- opening++;
- else if (data[i] == cclose)
- closing++;
-
- i++;
- }
-
- if (closing != opening)
- link_end--;
- }
-
- return link_end;
-}
-
-static size_t
-check_domain(uint8_t *data, size_t size, int allow_short)
-{
- size_t i, np = 0;
-
- if (!isalnum(data[0]))
- return 0;
-
- for (i = 1; i < size - 1; ++i) {
- if (data[i] == '.') np++;
- else if (!isalnum(data[i]) && data[i] != '-') break;
- }
-
- if (allow_short) {
- /* We don't need a valid domain in the strict sense (with
- * least one dot; so just make sure it's composed of valid
- * domain characters and return the length of the the valid
- * sequence. */
- return i;
- } else {
- /* a valid domain needs to have at least a dot.
- * that's as far as we get */
- return np ? i : 0;
- }
-}
-
-size_t
-sd_autolink__www(
- size_t *rewind_p,
- struct buf *link,
- uint8_t *data,
- size_t max_rewind,
- size_t size,
- unsigned int flags)
-{
- size_t link_end;
-
- if (max_rewind > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
- return 0;
-
- if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0)
- return 0;
-
- link_end = check_domain(data, size, 0);
-
- if (link_end == 0)
- return 0;
-
- while (link_end < size && !isspace(data[link_end]))
- link_end++;
-
- link_end = autolink_delim(data, link_end, max_rewind, size);
-
- if (link_end == 0)
- return 0;
-
- bufput(link, data, link_end);
- *rewind_p = 0;
-
- return (int)link_end;
-}
-
-size_t
-sd_autolink__email(
- size_t *rewind_p,
- struct buf *link,
- uint8_t *data,
- size_t max_rewind,
- size_t size,
- unsigned int flags)
-{
- size_t link_end, rewind;
- int nb = 0, np = 0;
-
- for (rewind = 0; rewind < max_rewind; ++rewind) {
- uint8_t c = data[-rewind - 1];
-
- if (isalnum(c))
- continue;
-
- if (strchr(".+-_", c) != NULL)
- continue;
-
- break;
- }
-
- if (rewind == 0)
- return 0;
-
- for (link_end = 0; link_end < size; ++link_end) {
- uint8_t c = data[link_end];
-
- if (isalnum(c))
- continue;
-
- if (c == '@')
- nb++;
- else if (c == '.' && link_end < size - 1)
- np++;
- else if (c != '-' && c != '_')
- break;
- }
-
- if (link_end < 2 || nb != 1 || np == 0 ||
- !isalpha(data[link_end - 1]))
- return 0;
-
- link_end = autolink_delim(data, link_end, max_rewind, size);
-
- if (link_end == 0)
- return 0;
-
- bufput(link, data - rewind, link_end + rewind);
- *rewind_p = rewind;
-
- return link_end;
-}
-
-size_t
-sd_autolink__url(
- size_t *rewind_p,
- struct buf *link,
- uint8_t *data,
- size_t max_rewind,
- size_t size,
- unsigned int flags)
-{
- size_t link_end, rewind = 0, domain_len;
-
- if (size < 4 || data[1] != '/' || data[2] != '/')
- return 0;
-
- while (rewind < max_rewind && isalpha(data[-rewind - 1]))
- rewind++;
-
- if (!sd_autolink_issafe(data - rewind, size + rewind))
- return 0;
-
- link_end = strlen("://");
-
- domain_len = check_domain(
- data + link_end,
- size - link_end,
- flags & SD_AUTOLINK_SHORT_DOMAINS);
-
- if (domain_len == 0)
- return 0;
-
- link_end += domain_len;
- while (link_end < size && !isspace(data[link_end]))
- link_end++;
-
- link_end = autolink_delim(data, link_end, max_rewind, size);
-
- if (link_end == 0)
- return 0;
-
- bufput(link, data - rewind, link_end + rewind);
- *rewind_p = rewind;
-
- return link_end;
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2011, Vicent Marti
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef UPSKIRT_AUTOLINK_H
-#define UPSKIRT_AUTOLINK_H
-
-#include "buffer.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum {
- SD_AUTOLINK_SHORT_DOMAINS = (1 << 0),
-};
-
-int
-sd_autolink_issafe(const uint8_t *link, size_t link_len);
-
-size_t
-sd_autolink__www(size_t *rewind_p, struct buf *link,
- uint8_t *data, size_t offset, size_t size, unsigned int flags);
-
-size_t
-sd_autolink__email(size_t *rewind_p, struct buf *link,
- uint8_t *data, size_t offset, size_t size, unsigned int flags);
-
-size_t
-sd_autolink__url(size_t *rewind_p, struct buf *link,
- uint8_t *data, size_t offset, size_t size, unsigned int flags);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-/* vim: set filetype=c: */
+++ /dev/null
-/*
- * Copyright (c) 2008, Natacha Porté
- * Copyright (c) 2011, Vicent MartÃ
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define BUFFER_MAX_ALLOC_SIZE (1024 * 1024 * 16) //16mb
-
-#include "buffer.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-/* MSVC compat */
-#if defined(_MSC_VER)
-# define _buf_vsnprintf _vsnprintf
-#else
-# define _buf_vsnprintf vsnprintf
-#endif
-
-int
-bufprefix(const struct buf *buf, const char *prefix)
-{
- size_t i;
- assert(buf && buf->unit);
-
- for (i = 0; i < buf->size; ++i) {
- if (prefix[i] == 0)
- return 0;
-
- if (buf->data[i] != prefix[i])
- return buf->data[i] - prefix[i];
- }
-
- return 0;
-}
-
-/* bufgrow: increasing the allocated size to the given value */
-int
-bufgrow(struct buf *buf, size_t neosz)
-{
- size_t neoasz;
- void *neodata;
-
- assert(buf && buf->unit);
-
- if (neosz > BUFFER_MAX_ALLOC_SIZE)
- return BUF_ENOMEM;
-
- if (buf->asize >= neosz)
- return BUF_OK;
-
- neoasz = buf->asize + buf->unit;
- while (neoasz < neosz)
- neoasz += buf->unit;
-
- neodata = realloc(buf->data, neoasz);
- if (!neodata)
- return BUF_ENOMEM;
-
- buf->data = neodata;
- buf->asize = neoasz;
- return BUF_OK;
-}
-
-
-/* bufnew: allocation of a new buffer */
-struct buf *
-bufnew(size_t unit)
-{
- struct buf *ret;
- ret = malloc(sizeof (struct buf));
-
- if (ret) {
- ret->data = 0;
- ret->size = ret->asize = 0;
- ret->unit = unit;
- }
- return ret;
-}
-
-/* bufnullterm: NULL-termination of the string array */
-const char *
-bufcstr(struct buf *buf)
-{
- assert(buf && buf->unit);
-
- if (buf->size < buf->asize && buf->data[buf->size] == 0)
- return (char *)buf->data;
-
- if (buf->size + 1 <= buf->asize || bufgrow(buf, buf->size + 1) == 0) {
- buf->data[buf->size] = 0;
- return (char *)buf->data;
- }
-
- return NULL;
-}
-
-/* bufprintf: formatted printing to a buffer */
-void
-bufprintf(struct buf *buf, const char *fmt, ...)
-{
- va_list ap;
- int n;
-
- assert(buf && buf->unit);
-
- if (buf->size >= buf->asize && bufgrow(buf, buf->size + 1) < 0)
- return;
-
- va_start(ap, fmt);
- n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
- va_end(ap);
-
- if (n < 0) {
-#ifdef _MSC_VER
- va_start(ap, fmt);
- n = _vscprintf(fmt, ap);
- va_end(ap);
-#else
- return;
-#endif
- }
-
- if ((size_t)n >= buf->asize - buf->size) {
- if (bufgrow(buf, buf->size + n + 1) < 0)
- return;
-
- va_start(ap, fmt);
- n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
- va_end(ap);
- }
-
- if (n < 0)
- return;
-
- buf->size += n;
-}
-
-/* bufput: appends raw data to a buffer */
-void
-bufput(struct buf *buf, const void *data, size_t len)
-{
- assert(buf && buf->unit);
-
- if (buf->size + len > buf->asize && bufgrow(buf, buf->size + len) < 0)
- return;
-
- memcpy(buf->data + buf->size, data, len);
- buf->size += len;
-}
-
-/* bufputs: appends a NUL-terminated string to a buffer */
-void
-bufputs(struct buf *buf, const char *str)
-{
- bufput(buf, str, strlen(str));
-}
-
-
-/* bufputc: appends a single uint8_t to a buffer */
-void
-bufputc(struct buf *buf, int c)
-{
- assert(buf && buf->unit);
-
- if (buf->size + 1 > buf->asize && bufgrow(buf, buf->size + 1) < 0)
- return;
-
- buf->data[buf->size] = c;
- buf->size += 1;
-}
-
-/* bufrelease: decrease the reference count and free the buffer if needed */
-void
-bufrelease(struct buf *buf)
-{
- if (!buf)
- return;
-
- free(buf->data);
- free(buf);
-}
-
-
-/* bufreset: frees internal data of the buffer */
-void
-bufreset(struct buf *buf)
-{
- if (!buf)
- return;
-
- free(buf->data);
- buf->data = NULL;
- buf->size = buf->asize = 0;
-}
-
-/* bufslurp: removes a given number of bytes from the head of the array */
-void
-bufslurp(struct buf *buf, size_t len)
-{
- assert(buf && buf->unit);
-
- if (len >= buf->size) {
- buf->size = 0;
- return;
- }
-
- buf->size -= len;
- memmove(buf->data, buf->data + len, buf->size);
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2008, Natacha Porté
- * Copyright (c) 2011, Vicent MartÃ
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef BUFFER_H__
-#define BUFFER_H__
-
-#include <stddef.h>
-#include <stdarg.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(_MSC_VER)
-#define __attribute__(x)
-#define inline
-#endif
-
-typedef enum {
- BUF_OK = 0,
- BUF_ENOMEM = -1,
-} buferror_t;
-
-/* struct buf: character array buffer */
-struct buf {
- uint8_t *data; /* actual character data */
- size_t size; /* size of the string */
- size_t asize; /* allocated size (0 = volatile buffer) */
- size_t unit; /* reallocation unit size (0 = read-only buffer) */
-};
-
-/* CONST_BUF: global buffer from a string litteral */
-#define BUF_STATIC(string) \
- { (uint8_t *)string, sizeof string -1, sizeof string, 0, 0 }
-
-/* VOLATILE_BUF: macro for creating a volatile buffer on the stack */
-#define BUF_VOLATILE(strname) \
- { (uint8_t *)strname, strlen(strname), 0, 0, 0 }
-
-/* BUFPUTSL: optimized bufputs of a string litteral */
-#define BUFPUTSL(output, literal) \
- bufput(output, literal, sizeof literal - 1)
-
-/* bufgrow: increasing the allocated size to the given value */
-int bufgrow(struct buf *, size_t);
-
-/* bufnew: allocation of a new buffer */
-struct buf *bufnew(size_t) __attribute__ ((malloc));
-
-/* bufnullterm: NUL-termination of the string array (making a C-string) */
-const char *bufcstr(struct buf *);
-
-/* bufprefix: compare the beginning of a buffer with a string */
-int bufprefix(const struct buf *buf, const char *prefix);
-
-/* bufput: appends raw data to a buffer */
-void bufput(struct buf *, const void *, size_t);
-
-/* bufputs: appends a NUL-terminated string to a buffer */
-void bufputs(struct buf *, const char *);
-
-/* bufputc: appends a single char to a buffer */
-void bufputc(struct buf *, int);
-
-/* bufrelease: decrease the reference count and free the buffer if needed */
-void bufrelease(struct buf *);
-
-/* bufreset: frees internal data of the buffer */
-void bufreset(struct buf *);
-
-/* bufslurp: removes a given number of bytes from the head of the array */
-void bufslurp(struct buf *, size_t);
-
-/* bufprintf: formatted printing to a buffer */
-void bufprintf(struct buf *, const char *, ...) __attribute__ ((format (printf, 2, 3)));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+++ /dev/null
-/* C code produced by gperf version 3.0.3 */
-/* Command-line: gperf -N find_block_tag -H hash_block_tag -C -c -E --ignore-case html_block_names.txt */
-/* Computed positions: -k'1-2' */
-
-#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
- && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
- && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
- && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
- && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
- && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
- && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
- && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
- && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
- && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
- && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
- && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
- && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
- && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
- && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
- && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
- && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
- && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
- && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
- && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
- && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
- && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
- && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
-/* The character set is not based on ISO-646. */
-error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
-#endif
-
-/* maximum key range = 37, duplicates = 0 */
-
-#ifndef GPERF_DOWNCASE
-#define GPERF_DOWNCASE 1
-static unsigned char gperf_downcase[256] =
- {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
- 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,
- 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
- 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
- 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
- 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
- 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
- 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
- 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
- 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
- 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
- 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
- 255
- };
-#endif
-
-#ifndef GPERF_CASE_STRNCMP
-#define GPERF_CASE_STRNCMP 1
-static int
-gperf_case_strncmp (s1, s2, n)
- register const char *s1;
- register const char *s2;
- register unsigned int n;
-{
- for (; n > 0;)
- {
- unsigned char c1 = gperf_downcase[(unsigned char)*s1++];
- unsigned char c2 = gperf_downcase[(unsigned char)*s2++];
- if (c1 != 0 && c1 == c2)
- {
- n--;
- continue;
- }
- return (int)c1 - (int)c2;
- }
- return 0;
-}
-#endif
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-static unsigned int
-hash_block_tag (str, len)
- register const char *str;
- register unsigned int len;
-{
- static const unsigned char asso_values[] =
- {
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 8, 30, 25, 20, 15, 10, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 0, 38, 0, 38,
- 5, 5, 5, 15, 0, 38, 38, 0, 15, 10,
- 0, 38, 38, 15, 0, 5, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 0, 38,
- 0, 38, 5, 5, 5, 15, 0, 38, 38, 0,
- 15, 10, 0, 38, 38, 15, 0, 5, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38
- };
- register int hval = len;
-
- switch (hval)
- {
- default:
- hval += asso_values[(unsigned char)str[1]+1];
- /*FALLTHROUGH*/
- case 1:
- hval += asso_values[(unsigned char)str[0]];
- break;
- }
- return hval;
-}
-
-#ifdef __GNUC__
-__inline
-#ifdef __GNUC_STDC_INLINE__
-__attribute__ ((__gnu_inline__))
-#endif
-#endif
-const char *
-find_block_tag (str, len)
- register const char *str;
- register unsigned int len;
-{
- enum
- {
- TOTAL_KEYWORDS = 24,
- MIN_WORD_LENGTH = 1,
- MAX_WORD_LENGTH = 10,
- MIN_HASH_VALUE = 1,
- MAX_HASH_VALUE = 37
- };
-
- static const char * const wordlist[] =
- {
- "",
- "p",
- "dl",
- "div",
- "math",
- "table",
- "",
- "ul",
- "del",
- "form",
- "blockquote",
- "figure",
- "ol",
- "fieldset",
- "",
- "h1",
- "",
- "h6",
- "pre",
- "", "",
- "script",
- "h5",
- "noscript",
- "",
- "style",
- "iframe",
- "h4",
- "ins",
- "", "", "",
- "h3",
- "", "", "", "",
- "h2"
- };
-
- if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
- {
- register int key = hash_block_tag (str, len);
-
- if (key <= MAX_HASH_VALUE && key >= 0)
- {
- register const char *s = wordlist[key];
-
- if ((((unsigned char)*str ^ (unsigned char)*s) & ~32) == 0 && !gperf_case_strncmp (str, s, len) && s[len] == '\0')
- return s;
- }
- }
- return 0;
-}
+++ /dev/null
-/* markdown.c - generic markdown parser */
-
-/*
- * Copyright (c) 2009, Natacha Porté
- * Copyright (c) 2011, Vicent Marti
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "markdown.h"
-#include "stack.h"
-
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdio.h>
-
-#if defined(_WIN32)
-#define strncasecmp _strnicmp
-#endif
-
-#define REF_TABLE_SIZE 8
-
-#define BUFFER_BLOCK 0
-#define BUFFER_SPAN 1
-
-#define MKD_LI_END 8 /* internal list flag */
-
-#define gperf_case_strncmp(s1, s2, n) strncasecmp(s1, s2, n)
-#define GPERF_DOWNCASE 1
-#define GPERF_CASE_STRNCMP 1
-#include "html_blocks.h"
-
-/***************
- * LOCAL TYPES *
- ***************/
-
-/* link_ref: reference to a link */
-struct link_ref {
- unsigned int id;
-
- struct buf *link;
- struct buf *title;
-
- struct link_ref *next;
-};
-
-/* char_trigger: function pointer to render active chars */
-/* returns the number of chars taken care of */
-/* data is the pointer of the beginning of the span */
-/* offset is the number of valid chars before data */
-struct sd_markdown;
-typedef size_t
-(*char_trigger)(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
-
-static size_t char_emphasis(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
-static size_t char_linebreak(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
-static size_t char_codespan(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
-static size_t char_escape(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
-static size_t char_entity(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
-static size_t char_langle_tag(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
-static size_t char_autolink_url(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
-static size_t char_autolink_email(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
-static size_t char_autolink_www(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
-static size_t char_link(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
-static size_t char_superscript(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
-
-enum markdown_char_t {
- MD_CHAR_NONE = 0,
- MD_CHAR_EMPHASIS,
- MD_CHAR_CODESPAN,
- MD_CHAR_LINEBREAK,
- MD_CHAR_LINK,
- MD_CHAR_LANGLE,
- MD_CHAR_ESCAPE,
- MD_CHAR_ENTITITY,
- MD_CHAR_AUTOLINK_URL,
- MD_CHAR_AUTOLINK_EMAIL,
- MD_CHAR_AUTOLINK_WWW,
- MD_CHAR_SUPERSCRIPT,
-};
-
-static char_trigger markdown_char_ptrs[] = {
- NULL,
- &char_emphasis,
- &char_codespan,
- &char_linebreak,
- &char_link,
- &char_langle_tag,
- &char_escape,
- &char_entity,
- &char_autolink_url,
- &char_autolink_email,
- &char_autolink_www,
- &char_superscript,
-};
-
-/* render • structure containing one particular render */
-struct sd_markdown {
- struct sd_callbacks cb;
- void *opaque;
-
- struct link_ref *refs[REF_TABLE_SIZE];
- uint8_t active_char[256];
- struct stack work_bufs[2];
- unsigned int ext_flags;
- size_t max_nesting;
- int in_link_body;
-};
-
-/***************************
- * HELPER FUNCTIONS *
- ***************************/
-
-static inline struct buf *
-rndr_newbuf(struct sd_markdown *rndr, int type)
-{
- static const size_t buf_size[2] = {256, 64};
- struct buf *work = NULL;
- struct stack *pool = &rndr->work_bufs[type];
-
- if (pool->size < pool->asize &&
- pool->item[pool->size] != NULL) {
- work = pool->item[pool->size++];
- work->size = 0;
- } else {
- work = bufnew(buf_size[type]);
- stack_push(pool, work);
- }
-
- return work;
-}
-
-static inline void
-rndr_popbuf(struct sd_markdown *rndr, int type)
-{
- rndr->work_bufs[type].size--;
-}
-
-static void
-unscape_text(struct buf *ob, struct buf *src)
-{
- size_t i = 0, org;
- while (i < src->size) {
- org = i;
- while (i < src->size && src->data[i] != '\\')
- i++;
-
- if (i > org)
- bufput(ob, src->data + org, i - org);
-
- if (i + 1 >= src->size)
- break;
-
- bufputc(ob, src->data[i + 1]);
- i += 2;
- }
-}
-
-static unsigned int
-hash_link_ref(const uint8_t *link_ref, size_t length)
-{
- size_t i;
- unsigned int hash = 0;
-
- for (i = 0; i < length; ++i)
- hash = tolower(link_ref[i]) + (hash << 6) + (hash << 16) - hash;
-
- return hash;
-}
-
-static struct link_ref *
-add_link_ref(
- struct link_ref **references,
- const uint8_t *name, size_t name_size)
-{
- struct link_ref *ref = calloc(1, sizeof(struct link_ref));
-
- if (!ref)
- return NULL;
-
- ref->id = hash_link_ref(name, name_size);
- ref->next = references[ref->id % REF_TABLE_SIZE];
-
- references[ref->id % REF_TABLE_SIZE] = ref;
- return ref;
-}
-
-static struct link_ref *
-find_link_ref(struct link_ref **references, uint8_t *name, size_t length)
-{
- unsigned int hash = hash_link_ref(name, length);
- struct link_ref *ref = NULL;
-
- ref = references[hash % REF_TABLE_SIZE];
-
- while (ref != NULL) {
- if (ref->id == hash)
- return ref;
-
- ref = ref->next;
- }
-
- return NULL;
-}
-
-static void
-free_link_refs(struct link_ref **references)
-{
- size_t i;
-
- for (i = 0; i < REF_TABLE_SIZE; ++i) {
- struct link_ref *r = references[i];
- struct link_ref *next;
-
- while (r) {
- next = r->next;
- bufrelease(r->link);
- bufrelease(r->title);
- free(r);
- r = next;
- }
- }
-}
-
-/*
- * Check whether a char is a Markdown space.
-
- * Right now we only consider spaces the actual
- * space and a newline: tabs and carriage returns
- * are filtered out during the preprocessing phase.
- *
- * If we wanted to actually be UTF-8 compliant, we
- * should instead extract an Unicode codepoint from
- * this character and check for space properties.
- */
-static inline int
-_isspace(int c)
-{
- return c == ' ' || c == '\n';
-}
-
-/****************************
- * INLINE PARSING FUNCTIONS *
- ****************************/
-
-/* is_mail_autolink • looks for the address part of a mail autolink and '>' */
-/* this is less strict than the original markdown e-mail address matching */
-static size_t
-is_mail_autolink(uint8_t *data, size_t size)
-{
- size_t i = 0, nb = 0;
-
- /* address is assumed to be: [-@._a-zA-Z0-9]+ with exactly one '@' */
- for (i = 0; i < size; ++i) {
- if (isalnum(data[i]))
- continue;
-
- switch (data[i]) {
- case '@':
- nb++;
-
- case '-':
- case '.':
- case '_':
- break;
-
- case '>':
- return (nb == 1) ? i + 1 : 0;
-
- default:
- return 0;
- }
- }
-
- return 0;
-}
-
-/* tag_length • returns the length of the given tag, or 0 is it's not valid */
-static size_t
-tag_length(uint8_t *data, size_t size, enum mkd_autolink *autolink)
-{
- size_t i, j;
-
- /* a valid tag can't be shorter than 3 chars */
- if (size < 3) return 0;
-
- /* begins with a '<' optionally followed by '/', followed by letter or number */
- if (data[0] != '<') return 0;
- i = (data[1] == '/') ? 2 : 1;
-
- if (!isalnum(data[i]))
- return 0;
-
- /* scheme test */
- *autolink = MKDA_NOT_AUTOLINK;
-
- /* try to find the beginning of an URI */
- while (i < size && (isalnum(data[i]) || data[i] == '.' || data[i] == '+' || data[i] == '-'))
- i++;
-
- if (i > 1 && data[i] == '@') {
- if ((j = is_mail_autolink(data + i, size - i)) != 0) {
- *autolink = MKDA_EMAIL;
- return i + j;
- }
- }
-
- if (i > 2 && data[i] == ':') {
- *autolink = MKDA_NORMAL;
- i++;
- }
-
- /* completing autolink test: no whitespace or ' or " */
- if (i >= size)
- *autolink = MKDA_NOT_AUTOLINK;
-
- else if (*autolink) {
- j = i;
-
- while (i < size) {
- if (data[i] == '\\') i += 2;
- else if (data[i] == '>' || data[i] == '\'' ||
- data[i] == '"' || data[i] == ' ' || data[i] == '\n')
- break;
- else i++;
- }
-
- if (i >= size) return 0;
- if (i > j && data[i] == '>') return i + 1;
- /* one of the forbidden chars has been found */
- *autolink = MKDA_NOT_AUTOLINK;
- }
-
- /* looking for sometinhg looking like a tag end */
- while (i < size && data[i] != '>') i++;
- if (i >= size) return 0;
- return i + 1;
-}
-
-/* parse_inline • parses inline markdown elements */
-static void
-parse_inline(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size)
-{
- size_t i = 0, end = 0;
- uint8_t action = 0;
- struct buf work = { 0, 0, 0, 0 };
-
- if (rndr->work_bufs[BUFFER_SPAN].size +
- rndr->work_bufs[BUFFER_BLOCK].size > rndr->max_nesting)
- return;
-
- while (i < size) {
- /* copying inactive chars into the output */
- while (end < size && (action = rndr->active_char[data[end]]) == 0) {
- end++;
- }
-
- if (rndr->cb.normal_text) {
- work.data = data + i;
- work.size = end - i;
- rndr->cb.normal_text(ob, &work, rndr->opaque);
- }
- else
- bufput(ob, data + i, end - i);
-
- if (end >= size) break;
- i = end;
-
- end = markdown_char_ptrs[(int)action](ob, rndr, data + i, i, size - i);
- if (!end) /* no action from the callback */
- end = i + 1;
- else {
- i += end;
- end = i;
- }
- }
-}
-
-/* find_emph_char • looks for the next emph uint8_t, skipping other constructs */
-static size_t
-find_emph_char(uint8_t *data, size_t size, uint8_t c)
-{
- size_t i = 1;
-
- while (i < size) {
- while (i < size && data[i] != c && data[i] != '`' && data[i] != '[')
- i++;
-
- if (i == size)
- return 0;
-
- if (data[i] == c)
- return i;
-
- /* not counting escaped chars */
- if (i && data[i - 1] == '\\') {
- i++; continue;
- }
-
- if (data[i] == '`') {
- size_t span_nb = 0, bt;
- size_t tmp_i = 0;
-
- /* counting the number of opening backticks */
- while (i < size && data[i] == '`') {
- i++; span_nb++;
- }
-
- if (i >= size) return 0;
-
- /* finding the matching closing sequence */
- bt = 0;
- while (i < size && bt < span_nb) {
- if (!tmp_i && data[i] == c) tmp_i = i;
- if (data[i] == '`') bt++;
- else bt = 0;
- i++;
- }
-
- if (i >= size) return tmp_i;
- }
- /* skipping a link */
- else if (data[i] == '[') {
- size_t tmp_i = 0;
- uint8_t cc;
-
- i++;
- while (i < size && data[i] != ']') {
- if (!tmp_i && data[i] == c) tmp_i = i;
- i++;
- }
-
- i++;
- while (i < size && (data[i] == ' ' || data[i] == '\n'))
- i++;
-
- if (i >= size)
- return tmp_i;
-
- switch (data[i]) {
- case '[':
- cc = ']'; break;
-
- case '(':
- cc = ')'; break;
-
- default:
- if (tmp_i)
- return tmp_i;
- else
- continue;
- }
-
- i++;
- while (i < size && data[i] != cc) {
- if (!tmp_i && data[i] == c) tmp_i = i;
- i++;
- }
-
- if (i >= size)
- return tmp_i;
-
- i++;
- }
- }
-
- return 0;
-}
-
-/* parse_emph1 • parsing single emphase */
-/* closed by a symbol not preceded by whitespace and not followed by symbol */
-static size_t
-parse_emph1(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, uint8_t c)
-{
- size_t i = 0, len;
- struct buf *work = 0;
- int r;
-
- if (!rndr->cb.emphasis) return 0;
-
- /* skipping one symbol if coming from emph3 */
- if (size > 1 && data[0] == c && data[1] == c) i = 1;
-
- while (i < size) {
- len = find_emph_char(data + i, size - i, c);
- if (!len) return 0;
- i += len;
- if (i >= size) return 0;
-
- if (data[i] == c && !_isspace(data[i - 1])) {
-
- if (rndr->ext_flags & MKDEXT_NO_INTRA_EMPHASIS) {
- if (i + 1 < size && isalnum(data[i + 1]))
- continue;
- }
-
- work = rndr_newbuf(rndr, BUFFER_SPAN);
- parse_inline(work, rndr, data, i);
- r = rndr->cb.emphasis(ob, work, rndr->opaque);
- rndr_popbuf(rndr, BUFFER_SPAN);
- return r ? i + 1 : 0;
- }
- }
-
- return 0;
-}
-
-/* parse_emph2 • parsing single emphase */
-static size_t
-parse_emph2(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, uint8_t c)
-{
- int (*render_method)(struct buf *ob, const struct buf *text, void *opaque);
- size_t i = 0, len;
- struct buf *work = 0;
- int r;
-
- render_method = (c == '~') ? rndr->cb.strikethrough : rndr->cb.double_emphasis;
-
- if (!render_method)
- return 0;
-
- while (i < size) {
- len = find_emph_char(data + i, size - i, c);
- if (!len) return 0;
- i += len;
-
- if (i + 1 < size && data[i] == c && data[i + 1] == c && i && !_isspace(data[i - 1])) {
- work = rndr_newbuf(rndr, BUFFER_SPAN);
- parse_inline(work, rndr, data, i);
- r = render_method(ob, work, rndr->opaque);
- rndr_popbuf(rndr, BUFFER_SPAN);
- return r ? i + 2 : 0;
- }
- i++;
- }
- return 0;
-}
-
-/* parse_emph3 • parsing single emphase */
-/* finds the first closing tag, and delegates to the other emph */
-static size_t
-parse_emph3(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, uint8_t c)
-{
- size_t i = 0, len;
- int r;
-
- while (i < size) {
- len = find_emph_char(data + i, size - i, c);
- if (!len) return 0;
- i += len;
-
- /* skip whitespace preceded symbols */
- if (data[i] != c || _isspace(data[i - 1]))
- continue;
-
- if (i + 2 < size && data[i + 1] == c && data[i + 2] == c && rndr->cb.triple_emphasis) {
- /* triple symbol found */
- struct buf *work = rndr_newbuf(rndr, BUFFER_SPAN);
-
- parse_inline(work, rndr, data, i);
- r = rndr->cb.triple_emphasis(ob, work, rndr->opaque);
- rndr_popbuf(rndr, BUFFER_SPAN);
- return r ? i + 3 : 0;
-
- } else if (i + 1 < size && data[i + 1] == c) {
- /* double symbol found, handing over to emph1 */
- len = parse_emph1(ob, rndr, data - 2, size + 2, c);
- if (!len) return 0;
- else return len - 2;
-
- } else {
- /* single symbol found, handing over to emph2 */
- len = parse_emph2(ob, rndr, data - 1, size + 1, c);
- if (!len) return 0;
- else return len - 1;
- }
- }
- return 0;
-}
-
-/* char_emphasis • single and double emphasis parsing */
-static size_t
-char_emphasis(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
-{
- uint8_t c = data[0];
- size_t ret;
-
- if (rndr->ext_flags & MKDEXT_NO_INTRA_EMPHASIS) {
- if (offset > 0 && !_isspace(data[-1]) && data[-1] != '>')
- return 0;
- }
-
- if (size > 2 && data[1] != c) {
- /* whitespace cannot follow an opening emphasis;
- * strikethrough only takes two characters '~~' */
- if (c == '~' || _isspace(data[1]) || (ret = parse_emph1(ob, rndr, data + 1, size - 1, c)) == 0)
- return 0;
-
- return ret + 1;
- }
-
- if (size > 3 && data[1] == c && data[2] != c) {
- if (_isspace(data[2]) || (ret = parse_emph2(ob, rndr, data + 2, size - 2, c)) == 0)
- return 0;
-
- return ret + 2;
- }
-
- if (size > 4 && data[1] == c && data[2] == c && data[3] != c) {
- if (c == '~' || _isspace(data[3]) || (ret = parse_emph3(ob, rndr, data + 3, size - 3, c)) == 0)
- return 0;
-
- return ret + 3;
- }
-
- return 0;
-}
-
-
-/* char_linebreak • '\n' preceded by two spaces (assuming linebreak != 0) */
-static size_t
-char_linebreak(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
-{
- if (offset < 2 || data[-1] != ' ' || data[-2] != ' ')
- return 0;
-
- /* removing the last space from ob and rendering */
- while (ob->size && ob->data[ob->size - 1] == ' ')
- ob->size--;
-
- return rndr->cb.linebreak(ob, rndr->opaque) ? 1 : 0;
-}
-
-
-/* char_codespan • '`' parsing a code span (assuming codespan != 0) */
-static size_t
-char_codespan(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
-{
- size_t end, nb = 0, i, f_begin, f_end;
-
- /* counting the number of backticks in the delimiter */
- while (nb < size && data[nb] == '`')
- nb++;
-
- /* finding the next delimiter */
- i = 0;
- for (end = nb; end < size && i < nb; end++) {
- if (data[end] == '`') i++;
- else i = 0;
- }
-
- if (i < nb && end >= size)
- return 0; /* no matching delimiter */
-
- /* trimming outside whitespaces */
- f_begin = nb;
- while (f_begin < end && data[f_begin] == ' ')
- f_begin++;
-
- f_end = end - nb;
- while (f_end > nb && data[f_end-1] == ' ')
- f_end--;
-
- /* real code span */
- if (f_begin < f_end) {
- struct buf work = { data + f_begin, f_end - f_begin, 0, 0 };
- if (!rndr->cb.codespan(ob, &work, rndr->opaque))
- end = 0;
- } else {
- if (!rndr->cb.codespan(ob, 0, rndr->opaque))
- end = 0;
- }
-
- return end;
-}
-
-
-/* char_escape • '\\' backslash escape */
-static size_t
-char_escape(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
-{
- static const char *escape_chars = "\\`*_{}[]()#+-.!:|&<>^~";
- struct buf work = { 0, 0, 0, 0 };
-
- if (size > 1) {
- if (strchr(escape_chars, data[1]) == NULL)
- return 0;
-
- if (rndr->cb.normal_text) {
- work.data = data + 1;
- work.size = 1;
- rndr->cb.normal_text(ob, &work, rndr->opaque);
- }
- else bufputc(ob, data[1]);
- } else if (size == 1) {
- bufputc(ob, data[0]);
- }
-
- return 2;
-}
-
-/* char_entity • '&' escaped when it doesn't belong to an entity */
-/* valid entities are assumed to be anything matching &#?[A-Za-z0-9]+; */
-static size_t
-char_entity(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
-{
- size_t end = 1;
- struct buf work = { 0, 0, 0, 0 };
-
- if (end < size && data[end] == '#')
- end++;
-
- while (end < size && isalnum(data[end]))
- end++;
-
- if (end < size && data[end] == ';')
- end++; /* real entity */
- else
- return 0; /* lone '&' */
-
- if (rndr->cb.entity) {
- work.data = data;
- work.size = end;
- rndr->cb.entity(ob, &work, rndr->opaque);
- }
- else bufput(ob, data, end);
-
- return end;
-}
-
-/* char_langle_tag • '<' when tags or autolinks are allowed */
-static size_t
-char_langle_tag(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
-{
- enum mkd_autolink altype = MKDA_NOT_AUTOLINK;
- size_t end = tag_length(data, size, &altype);
- struct buf work = { data, end, 0, 0 };
- int ret = 0;
-
- if (end > 2) {
- if (rndr->cb.autolink && altype != MKDA_NOT_AUTOLINK) {
- struct buf *u_link = rndr_newbuf(rndr, BUFFER_SPAN);
- work.data = data + 1;
- work.size = end - 2;
- unscape_text(u_link, &work);
- ret = rndr->cb.autolink(ob, u_link, altype, rndr->opaque);
- rndr_popbuf(rndr, BUFFER_SPAN);
- }
- else if (rndr->cb.raw_html_tag)
- ret = rndr->cb.raw_html_tag(ob, &work, rndr->opaque);
- }
-
- if (!ret) return 0;
- else return end;
-}
-
-static size_t
-char_autolink_www(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
-{
- struct buf *link, *link_url, *link_text;
- size_t link_len, rewind;
-
- if (!rndr->cb.link || rndr->in_link_body)
- return 0;
-
- link = rndr_newbuf(rndr, BUFFER_SPAN);
-
- if ((link_len = sd_autolink__www(&rewind, link, data, offset, size, 0)) > 0) {
- link_url = rndr_newbuf(rndr, BUFFER_SPAN);
- BUFPUTSL(link_url, "http://");
- bufput(link_url, link->data, link->size);
-
- ob->size -= rewind;
- if (rndr->cb.normal_text) {
- link_text = rndr_newbuf(rndr, BUFFER_SPAN);
- rndr->cb.normal_text(link_text, link, rndr->opaque);
- rndr->cb.link(ob, link_url, NULL, link_text, rndr->opaque);
- rndr_popbuf(rndr, BUFFER_SPAN);
- } else {
- rndr->cb.link(ob, link_url, NULL, link, rndr->opaque);
- }
- rndr_popbuf(rndr, BUFFER_SPAN);
- }
-
- rndr_popbuf(rndr, BUFFER_SPAN);
- return link_len;
-}
-
-static size_t
-char_autolink_email(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
-{
- struct buf *link;
- size_t link_len, rewind;
-
- if (!rndr->cb.autolink || rndr->in_link_body)
- return 0;
-
- link = rndr_newbuf(rndr, BUFFER_SPAN);
-
- if ((link_len = sd_autolink__email(&rewind, link, data, offset, size, 0)) > 0) {
- ob->size -= rewind;
- rndr->cb.autolink(ob, link, MKDA_EMAIL, rndr->opaque);
- }
-
- rndr_popbuf(rndr, BUFFER_SPAN);
- return link_len;
-}
-
-static size_t
-char_autolink_url(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
-{
- struct buf *link;
- size_t link_len, rewind;
-
- if (!rndr->cb.autolink || rndr->in_link_body)
- return 0;
-
- link = rndr_newbuf(rndr, BUFFER_SPAN);
-
- if ((link_len = sd_autolink__url(&rewind, link, data, offset, size, 0)) > 0) {
- ob->size -= rewind;
- rndr->cb.autolink(ob, link, MKDA_NORMAL, rndr->opaque);
- }
-
- rndr_popbuf(rndr, BUFFER_SPAN);
- return link_len;
-}
-
-/* char_link • '[': parsing a link or an image */
-static size_t
-char_link(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
-{
- int is_img = (offset && data[-1] == '!'), level;
- size_t i = 1, txt_e, link_b = 0, link_e = 0, title_b = 0, title_e = 0;
- struct buf *content = 0;
- struct buf *link = 0;
- struct buf *title = 0;
- struct buf *u_link = 0;
- size_t org_work_size = rndr->work_bufs[BUFFER_SPAN].size;
- int text_has_nl = 0, ret = 0;
- int in_title = 0, qtype = 0;
-
- /* checking whether the correct renderer exists */
- if ((is_img && !rndr->cb.image) || (!is_img && !rndr->cb.link))
- goto cleanup;
-
- /* looking for the matching closing bracket */
- for (level = 1; i < size; i++) {
- if (data[i] == '\n')
- text_has_nl = 1;
-
- else if (data[i - 1] == '\\')
- continue;
-
- else if (data[i] == '[')
- level++;
-
- else if (data[i] == ']') {
- level--;
- if (level <= 0)
- break;
- }
- }
-
- if (i >= size)
- goto cleanup;
-
- txt_e = i;
- i++;
-
- /* skip any amount of whitespace or newline */
- /* (this is much more laxist than original markdown syntax) */
- while (i < size && _isspace(data[i]))
- i++;
-
- /* inline style link */
- if (i < size && data[i] == '(') {
- /* skipping initial whitespace */
- i++;
-
- while (i < size && _isspace(data[i]))
- i++;
-
- link_b = i;
-
- /* looking for link end: ' " ) */
- while (i < size) {
- if (data[i] == '\\') i += 2;
- else if (data[i] == ')') break;
- else if (i >= 1 && _isspace(data[i-1]) && (data[i] == '\'' || data[i] == '"')) break;
- else i++;
- }
-
- if (i >= size) goto cleanup;
- link_e = i;
-
- /* looking for title end if present */
- if (data[i] == '\'' || data[i] == '"') {
- qtype = data[i];
- in_title = 1;
- i++;
- title_b = i;
-
- while (i < size) {
- if (data[i] == '\\') i += 2;
- else if (data[i] == qtype) {in_title = 0; i++;}
- else if ((data[i] == ')') && !in_title) break;
- else i++;
- }
-
- if (i >= size) goto cleanup;
-
- /* skipping whitespaces after title */
- title_e = i - 1;
- while (title_e > title_b && _isspace(data[title_e]))
- title_e--;
-
- /* checking for closing quote presence */
- if (data[title_e] != '\'' && data[title_e] != '"') {
- title_b = title_e = 0;
- link_e = i;
- }
- }
-
- /* remove whitespace at the end of the link */
- while (link_e > link_b && _isspace(data[link_e - 1]))
- link_e--;
-
- /* remove optional angle brackets around the link */
- if (data[link_b] == '<') link_b++;
- if (data[link_e - 1] == '>') link_e--;
-
- /* building escaped link and title */
- if (link_e > link_b) {
- link = rndr_newbuf(rndr, BUFFER_SPAN);
- bufput(link, data + link_b, link_e - link_b);
- }
-
- if (title_e > title_b) {
- title = rndr_newbuf(rndr, BUFFER_SPAN);
- bufput(title, data + title_b, title_e - title_b);
- }
-
- i++;
- }
-
- /* reference style link */
- else if (i < size && data[i] == '[') {
- struct buf id = { 0, 0, 0, 0 };
- struct link_ref *lr;
-
- /* looking for the id */
- i++;
- link_b = i;
- while (i < size && data[i] != ']') i++;
- if (i >= size) goto cleanup;
- link_e = i;
-
- /* finding the link_ref */
- if (link_b == link_e) {
- if (text_has_nl) {
- struct buf *b = rndr_newbuf(rndr, BUFFER_SPAN);
- size_t j;
-
- for (j = 1; j < txt_e; j++) {
- if (data[j] != '\n')
- bufputc(b, data[j]);
- else if (data[j - 1] != ' ')
- bufputc(b, ' ');
- }
-
- id.data = b->data;
- id.size = b->size;
- } else {
- id.data = data + 1;
- id.size = txt_e - 1;
- }
- } else {
- id.data = data + link_b;
- id.size = link_e - link_b;
- }
-
- lr = find_link_ref(rndr->refs, id.data, id.size);
- if (!lr)
- goto cleanup;
-
- /* keeping link and title from link_ref */
- link = lr->link;
- title = lr->title;
- i++;
- }
-
- /* shortcut reference style link */
- else {
- struct buf id = { 0, 0, 0, 0 };
- struct link_ref *lr;
-
- /* crafting the id */
- if (text_has_nl) {
- struct buf *b = rndr_newbuf(rndr, BUFFER_SPAN);
- size_t j;
-
- for (j = 1; j < txt_e; j++) {
- if (data[j] != '\n')
- bufputc(b, data[j]);
- else if (data[j - 1] != ' ')
- bufputc(b, ' ');
- }
-
- id.data = b->data;
- id.size = b->size;
- } else {
- id.data = data + 1;
- id.size = txt_e - 1;
- }
-
- /* finding the link_ref */
- lr = find_link_ref(rndr->refs, id.data, id.size);
- if (!lr)
- goto cleanup;
-
- /* keeping link and title from link_ref */
- link = lr->link;
- title = lr->title;
-
- /* rewinding the whitespace */
- i = txt_e + 1;
- }
-
- /* building content: img alt is escaped, link content is parsed */
- if (txt_e > 1) {
- content = rndr_newbuf(rndr, BUFFER_SPAN);
- if (is_img) {
- bufput(content, data + 1, txt_e - 1);
- } else {
- /* disable autolinking when parsing inline the
- * content of a link */
- rndr->in_link_body = 1;
- parse_inline(content, rndr, data + 1, txt_e - 1);
- rndr->in_link_body = 0;
- }
- }
-
- if (link) {
- u_link = rndr_newbuf(rndr, BUFFER_SPAN);
- unscape_text(u_link, link);
- }
-
- /* calling the relevant rendering function */
- if (is_img) {
- if (ob->size && ob->data[ob->size - 1] == '!')
- ob->size -= 1;
-
- ret = rndr->cb.image(ob, u_link, title, content, rndr->opaque);
- } else {
- ret = rndr->cb.link(ob, u_link, title, content, rndr->opaque);
- }
-
- /* cleanup */
-cleanup:
- rndr->work_bufs[BUFFER_SPAN].size = (int)org_work_size;
- return ret ? i : 0;
-}
-
-static size_t
-char_superscript(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
-{
- size_t sup_start, sup_len;
- struct buf *sup;
-
- if (!rndr->cb.superscript)
- return 0;
-
- if (size < 2)
- return 0;
-
- if (data[1] == '(') {
- sup_start = sup_len = 2;
-
- while (sup_len < size && data[sup_len] != ')' && data[sup_len - 1] != '\\')
- sup_len++;
-
- if (sup_len == size)
- return 0;
- } else {
- sup_start = sup_len = 1;
-
- while (sup_len < size && !_isspace(data[sup_len]))
- sup_len++;
- }
-
- if (sup_len - sup_start == 0)
- return (sup_start == 2) ? 3 : 0;
-
- sup = rndr_newbuf(rndr, BUFFER_SPAN);
- parse_inline(sup, rndr, data + sup_start, sup_len - sup_start);
- rndr->cb.superscript(ob, sup, rndr->opaque);
- rndr_popbuf(rndr, BUFFER_SPAN);
-
- return (sup_start == 2) ? sup_len + 1 : sup_len;
-}
-
-/*********************************
- * BLOCK-LEVEL PARSING FUNCTIONS *
- *********************************/
-
-/* is_empty • returns the line length when it is empty, 0 otherwise */
-static size_t
-is_empty(uint8_t *data, size_t size)
-{
- size_t i;
-
- for (i = 0; i < size && data[i] != '\n'; i++)
- if (data[i] != ' ')
- return 0;
-
- return i + 1;
-}
-
-/* is_hrule • returns whether a line is a horizontal rule */
-static int
-is_hrule(uint8_t *data, size_t size)
-{
- size_t i = 0, n = 0;
- uint8_t c;
-
- /* skipping initial spaces */
- if (size < 3) return 0;
- if (data[0] == ' ') { i++;
- if (data[1] == ' ') { i++;
- if (data[2] == ' ') { i++; } } }
-
- /* looking at the hrule uint8_t */
- if (i + 2 >= size
- || (data[i] != '*' && data[i] != '-' && data[i] != '_'))
- return 0;
- c = data[i];
-
- /* the whole line must be the char or whitespace */
- while (i < size && data[i] != '\n') {
- if (data[i] == c) n++;
- else if (data[i] != ' ')
- return 0;
-
- i++;
- }
-
- return n >= 3;
-}
-
-/* check if a line begins with a code fence; return the
- * width of the code fence */
-static size_t
-prefix_codefence(uint8_t *data, size_t size)
-{
- size_t i = 0, n = 0;
- uint8_t c;
-
- /* skipping initial spaces */
- if (size < 3) return 0;
- if (data[0] == ' ') { i++;
- if (data[1] == ' ') { i++;
- if (data[2] == ' ') { i++; } } }
-
- /* looking at the hrule uint8_t */
- if (i + 2 >= size || !(data[i] == '~' || data[i] == '`'))
- return 0;
-
- c = data[i];
-
- /* the whole line must be the uint8_t or whitespace */
- while (i < size && data[i] == c) {
- n++; i++;
- }
-
- if (n < 3)
- return 0;
-
- return i;
-}
-
-/* check if a line is a code fence; return its size if it is */
-static size_t
-is_codefence(uint8_t *data, size_t size, struct buf *syntax)
-{
- size_t i = 0, syn_len = 0;
- uint8_t *syn_start;
-
- i = prefix_codefence(data, size);
- if (i == 0)
- return 0;
-
- while (i < size && data[i] == ' ')
- i++;
-
- syn_start = data + i;
-
- if (i < size && data[i] == '{') {
- i++; syn_start++;
-
- while (i < size && data[i] != '}' && data[i] != '\n') {
- syn_len++; i++;
- }
-
- if (i == size || data[i] != '}')
- return 0;
-
- /* strip all whitespace at the beginning and the end
- * of the {} block */
- while (syn_len > 0 && _isspace(syn_start[0])) {
- syn_start++; syn_len--;
- }
-
- while (syn_len > 0 && _isspace(syn_start[syn_len - 1]))
- syn_len--;
-
- i++;
- } else {
- while (i < size && !_isspace(data[i])) {
- syn_len++; i++;
- }
- }
-
- if (syntax) {
- syntax->data = syn_start;
- syntax->size = syn_len;
- }
-
- while (i < size && data[i] != '\n') {
- if (!_isspace(data[i]))
- return 0;
-
- i++;
- }
-
- return i + 1;
-}
-
-/* is_atxheader • returns whether the line is a hash-prefixed header */
-static int
-is_atxheader(struct sd_markdown *rndr, uint8_t *data, size_t size)
-{
- if (data[0] != '#')
- return 0;
-
- if (rndr->ext_flags & MKDEXT_SPACE_HEADERS) {
- size_t level = 0;
-
- while (level < size && level < 6 && data[level] == '#')
- level++;
-
- if (level < size && data[level] != ' ')
- return 0;
- }
-
- return 1;
-}
-
-/* is_headerline • returns whether the line is a setext-style hdr underline */
-static int
-is_headerline(uint8_t *data, size_t size)
-{
- size_t i = 0;
-
- /* test of level 1 header */
- if (data[i] == '=') {
- for (i = 1; i < size && data[i] == '='; i++);
- while (i < size && data[i] == ' ') i++;
- return (i >= size || data[i] == '\n') ? 1 : 0; }
-
- /* test of level 2 header */
- if (data[i] == '-') {
- for (i = 1; i < size && data[i] == '-'; i++);
- while (i < size && data[i] == ' ') i++;
- return (i >= size || data[i] == '\n') ? 2 : 0; }
-
- return 0;
-}
-
-static int
-is_next_headerline(uint8_t *data, size_t size)
-{
- size_t i = 0;
-
- while (i < size && data[i] != '\n')
- i++;
-
- if (++i >= size)
- return 0;
-
- return is_headerline(data + i, size - i);
-}
-
-/* prefix_quote • returns blockquote prefix length */
-static size_t
-prefix_quote(uint8_t *data, size_t size)
-{
- size_t i = 0;
- if (i < size && data[i] == ' ') i++;
- if (i < size && data[i] == ' ') i++;
- if (i < size && data[i] == ' ') i++;
-
- if (i < size && data[i] == '>') {
- if (i + 1 < size && data[i + 1] == ' ')
- return i + 2;
-
- return i + 1;
- }
-
- return 0;
-}
-
-/* prefix_code • returns prefix length for block code*/
-static size_t
-prefix_code(uint8_t *data, size_t size)
-{
- if (size > 3 && data[0] == ' ' && data[1] == ' '
- && data[2] == ' ' && data[3] == ' ') return 4;
-
- return 0;
-}
-
-/* prefix_oli • returns ordered list item prefix */
-static size_t
-prefix_oli(uint8_t *data, size_t size)
-{
- size_t i = 0;
-
- if (i < size && data[i] == ' ') i++;
- if (i < size && data[i] == ' ') i++;
- if (i < size && data[i] == ' ') i++;
-
- if (i >= size || data[i] < '0' || data[i] > '9')
- return 0;
-
- while (i < size && data[i] >= '0' && data[i] <= '9')
- i++;
-
- if (i + 1 >= size || data[i] != '.' || data[i + 1] != ' ')
- return 0;
-
- if (is_next_headerline(data + i, size - i))
- return 0;
-
- return i + 2;
-}
-
-/* prefix_uli • returns ordered list item prefix */
-static size_t
-prefix_uli(uint8_t *data, size_t size)
-{
- size_t i = 0;
-
- if (i < size && data[i] == ' ') i++;
- if (i < size && data[i] == ' ') i++;
- if (i < size && data[i] == ' ') i++;
-
- if (i + 1 >= size ||
- (data[i] != '*' && data[i] != '+' && data[i] != '-') ||
- data[i + 1] != ' ')
- return 0;
-
- if (is_next_headerline(data + i, size - i))
- return 0;
-
- return i + 2;
-}
-
-
-/* parse_block • parsing of one block, returning next uint8_t to parse */
-static void parse_block(struct buf *ob, struct sd_markdown *rndr,
- uint8_t *data, size_t size);
-
-
-/* parse_blockquote • handles parsing of a blockquote fragment */
-static size_t
-parse_blockquote(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size)
-{
- size_t beg, end = 0, pre, work_size = 0;
- uint8_t *work_data = 0;
- struct buf *out = 0;
-
- out = rndr_newbuf(rndr, BUFFER_BLOCK);
- beg = 0;
- while (beg < size) {
- for (end = beg + 1; end < size && data[end - 1] != '\n'; end++);
-
- pre = prefix_quote(data + beg, end - beg);
-
- if (pre)
- beg += pre; /* skipping prefix */
-
- /* empty line followed by non-quote line */
- else if (is_empty(data + beg, end - beg) &&
- (end >= size || (prefix_quote(data + end, size - end) == 0 &&
- !is_empty(data + end, size - end))))
- break;
-
- if (beg < end) { /* copy into the in-place working buffer */
- /* bufput(work, data + beg, end - beg); */
- if (!work_data)
- work_data = data + beg;
- else if (data + beg != work_data + work_size)
- memmove(work_data + work_size, data + beg, end - beg);
- work_size += end - beg;
- }
- beg = end;
- }
-
- parse_block(out, rndr, work_data, work_size);
- if (rndr->cb.blockquote)
- rndr->cb.blockquote(ob, out, rndr->opaque);
- rndr_popbuf(rndr, BUFFER_BLOCK);
- return end;
-}
-
-static size_t
-parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int do_render);
-
-/* parse_blockquote • handles parsing of a regular paragraph */
-static size_t
-parse_paragraph(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size)
-{
- size_t i = 0, end = 0;
- int level = 0;
- struct buf work = { data, 0, 0, 0 };
-
- while (i < size) {
- for (end = i + 1; end < size && data[end - 1] != '\n'; end++) /* empty */;
-
- if (is_empty(data + i, size - i))
- break;
-
- if ((level = is_headerline(data + i, size - i)) != 0)
- break;
-
- if (is_atxheader(rndr, data + i, size - i) ||
- is_hrule(data + i, size - i) ||
- prefix_quote(data + i, size - i)) {
- end = i;
- break;
- }
-
- /*
- * Early termination of a paragraph with the same logic
- * as Markdown 1.0.0. If this logic is applied, the
- * Markdown 1.0.3 test suite won't pass cleanly
- *
- * :: If the first character in a new line is not a letter,
- * let's check to see if there's some kind of block starting
- * here
- */
- if ((rndr->ext_flags & MKDEXT_LAX_SPACING) && !isalnum(data[i])) {
- if (prefix_oli(data + i, size - i) ||
- prefix_uli(data + i, size - i)) {
- end = i;
- break;
- }
-
- /* see if an html block starts here */
- if (data[i] == '<' && rndr->cb.blockhtml &&
- parse_htmlblock(ob, rndr, data + i, size - i, 0)) {
- end = i;
- break;
- }
-
- /* see if a code fence starts here */
- if ((rndr->ext_flags & MKDEXT_FENCED_CODE) != 0 &&
- is_codefence(data + i, size - i, NULL) != 0) {
- end = i;
- break;
- }
- }
-
- i = end;
- }
-
- work.size = i;
- while (work.size && data[work.size - 1] == '\n')
- work.size--;
-
- if (!level) {
- struct buf *tmp = rndr_newbuf(rndr, BUFFER_BLOCK);
- parse_inline(tmp, rndr, work.data, work.size);
- if (rndr->cb.paragraph)
- rndr->cb.paragraph(ob, tmp, rndr->opaque);
- rndr_popbuf(rndr, BUFFER_BLOCK);
- } else {
- struct buf *header_work;
-
- if (work.size) {
- size_t beg;
- i = work.size;
- work.size -= 1;
-
- while (work.size && data[work.size] != '\n')
- work.size -= 1;
-
- beg = work.size + 1;
- while (work.size && data[work.size - 1] == '\n')
- work.size -= 1;
-
- if (work.size > 0) {
- struct buf *tmp = rndr_newbuf(rndr, BUFFER_BLOCK);
- parse_inline(tmp, rndr, work.data, work.size);
-
- if (rndr->cb.paragraph)
- rndr->cb.paragraph(ob, tmp, rndr->opaque);
-
- rndr_popbuf(rndr, BUFFER_BLOCK);
- work.data += beg;
- work.size = i - beg;
- }
- else work.size = i;
- }
-
- header_work = rndr_newbuf(rndr, BUFFER_SPAN);
- parse_inline(header_work, rndr, work.data, work.size);
-
- if (rndr->cb.header)
- rndr->cb.header(ob, header_work, (int)level, rndr->opaque);
-
- rndr_popbuf(rndr, BUFFER_SPAN);
- }
-
- return end;
-}
-
-/* parse_fencedcode • handles parsing of a block-level code fragment */
-static size_t
-parse_fencedcode(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size)
-{
- size_t beg, end;
- struct buf *work = 0;
- struct buf lang = { 0, 0, 0, 0 };
-
- beg = is_codefence(data, size, &lang);
- if (beg == 0) return 0;
-
- work = rndr_newbuf(rndr, BUFFER_BLOCK);
-
- while (beg < size) {
- size_t fence_end;
- struct buf fence_trail = { 0, 0, 0, 0 };
-
- fence_end = is_codefence(data + beg, size - beg, &fence_trail);
- if (fence_end != 0 && fence_trail.size == 0) {
- beg += fence_end;
- break;
- }
-
- for (end = beg + 1; end < size && data[end - 1] != '\n'; end++);
-
- if (beg < end) {
- /* verbatim copy to the working buffer,
- escaping entities */
- if (is_empty(data + beg, end - beg))
- bufputc(work, '\n');
- else bufput(work, data + beg, end - beg);
- }
- beg = end;
- }
-
- if (work->size && work->data[work->size - 1] != '\n')
- bufputc(work, '\n');
-
- if (rndr->cb.blockcode)
- rndr->cb.blockcode(ob, work, lang.size ? &lang : NULL, rndr->opaque);
-
- rndr_popbuf(rndr, BUFFER_BLOCK);
- return beg;
-}
-
-static size_t
-parse_blockcode(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size)
-{
- size_t beg, end, pre;
- struct buf *work = 0;
-
- work = rndr_newbuf(rndr, BUFFER_BLOCK);
-
- beg = 0;
- while (beg < size) {
- for (end = beg + 1; end < size && data[end - 1] != '\n'; end++) {};
- pre = prefix_code(data + beg, end - beg);
-
- if (pre)
- beg += pre; /* skipping prefix */
- else if (!is_empty(data + beg, end - beg))
- /* non-empty non-prefixed line breaks the pre */
- break;
-
- if (beg < end) {
- /* verbatim copy to the working buffer,
- escaping entities */
- if (is_empty(data + beg, end - beg))
- bufputc(work, '\n');
- else bufput(work, data + beg, end - beg);
- }
- beg = end;
- }
-
- while (work->size && work->data[work->size - 1] == '\n')
- work->size -= 1;
-
- bufputc(work, '\n');
-
- if (rndr->cb.blockcode)
- rndr->cb.blockcode(ob, work, NULL, rndr->opaque);
-
- rndr_popbuf(rndr, BUFFER_BLOCK);
- return beg;
-}
-
-/* parse_listitem • parsing of a single list item */
-/* assuming initial prefix is already removed */
-static size_t
-parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int *flags)
-{
- struct buf *work = 0, *inter = 0;
- size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i;
- int in_empty = 0, has_inside_empty = 0, in_fence = 0;
-
- /* keeping track of the first indentation prefix */
- while (orgpre < 3 && orgpre < size && data[orgpre] == ' ')
- orgpre++;
-
- beg = prefix_uli(data, size);
- if (!beg)
- beg = prefix_oli(data, size);
-
- if (!beg)
- return 0;
-
- /* skipping to the beginning of the following line */
- end = beg;
- while (end < size && data[end - 1] != '\n')
- end++;
-
- /* getting working buffers */
- work = rndr_newbuf(rndr, BUFFER_SPAN);
- inter = rndr_newbuf(rndr, BUFFER_SPAN);
-
- /* putting the first line into the working buffer */
- bufput(work, data + beg, end - beg);
- beg = end;
-
- /* process the following lines */
- while (beg < size) {
- size_t has_next_uli = 0, has_next_oli = 0;
-
- end++;
-
- while (end < size && data[end - 1] != '\n')
- end++;
-
- /* process an empty line */
- if (is_empty(data + beg, end - beg)) {
- in_empty = 1;
- beg = end;
- continue;
- }
-
- /* calculating the indentation */
- i = 0;
- while (i < 4 && beg + i < end && data[beg + i] == ' ')
- i++;
-
- pre = i;
-
- if (rndr->ext_flags & MKDEXT_FENCED_CODE) {
- if (is_codefence(data + beg + i, end - beg - i, NULL) != 0)
- in_fence = !in_fence;
- }
-
- /* Only check for new list items if we are **not** inside
- * a fenced code block */
- if (!in_fence) {
- has_next_uli = prefix_uli(data + beg + i, end - beg - i);
- has_next_oli = prefix_oli(data + beg + i, end - beg - i);
- }
-
- /* checking for ul/ol switch */
- if (in_empty && (
- ((*flags & MKD_LIST_ORDERED) && has_next_uli) ||
- (!(*flags & MKD_LIST_ORDERED) && has_next_oli))){
- *flags |= MKD_LI_END;
- break; /* the following item must have same list type */
- }
-
- /* checking for a new item */
- if ((has_next_uli && !is_hrule(data + beg + i, end - beg - i)) || has_next_oli) {
- if (in_empty)
- has_inside_empty = 1;
-
- if (pre == orgpre) /* the following item must have */
- break; /* the same indentation */
-
- if (!sublist)
- sublist = work->size;
- }
- /* joining only indented stuff after empty lines;
- * note that now we only require 1 space of indentation
- * to continue a list */
- else if (in_empty && pre == 0) {
- *flags |= MKD_LI_END;
- break;
- }
- else if (in_empty) {
- bufputc(work, '\n');
- has_inside_empty = 1;
- }
-
- in_empty = 0;
-
- /* adding the line without prefix into the working buffer */
- bufput(work, data + beg + i, end - beg - i);
- beg = end;
- }
-
- /* render of li contents */
- if (has_inside_empty)
- *flags |= MKD_LI_BLOCK;
-
- if (*flags & MKD_LI_BLOCK) {
- /* intermediate render of block li */
- if (sublist && sublist < work->size) {
- parse_block(inter, rndr, work->data, sublist);
- parse_block(inter, rndr, work->data + sublist, work->size - sublist);
- }
- else
- parse_block(inter, rndr, work->data, work->size);
- } else {
- /* intermediate render of inline li */
- if (sublist && sublist < work->size) {
- parse_inline(inter, rndr, work->data, sublist);
- parse_block(inter, rndr, work->data + sublist, work->size - sublist);
- }
- else
- parse_inline(inter, rndr, work->data, work->size);
- }
-
- /* render of li itself */
- if (rndr->cb.listitem)
- rndr->cb.listitem(ob, inter, *flags, rndr->opaque);
-
- rndr_popbuf(rndr, BUFFER_SPAN);
- rndr_popbuf(rndr, BUFFER_SPAN);
- return beg;
-}
-
-
-/* parse_list • parsing ordered or unordered list block */
-static size_t
-parse_list(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int flags)
-{
- struct buf *work = 0;
- size_t i = 0, j;
-
- work = rndr_newbuf(rndr, BUFFER_BLOCK);
-
- while (i < size) {
- j = parse_listitem(work, rndr, data + i, size - i, &flags);
- i += j;
-
- if (!j || (flags & MKD_LI_END))
- break;
- }
-
- if (rndr->cb.list)
- rndr->cb.list(ob, work, flags, rndr->opaque);
- rndr_popbuf(rndr, BUFFER_BLOCK);
- return i;
-}
-
-/* parse_atxheader • parsing of atx-style headers */
-static size_t
-parse_atxheader(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size)
-{
- size_t level = 0;
- size_t i, end, skip;
-
- while (level < size && level < 6 && data[level] == '#')
- level++;
-
- for (i = level; i < size && data[i] == ' '; i++);
-
- for (end = i; end < size && data[end] != '\n'; end++);
- skip = end;
-
- while (end && data[end - 1] == '#')
- end--;
-
- while (end && data[end - 1] == ' ')
- end--;
-
- if (end > i) {
- struct buf *work = rndr_newbuf(rndr, BUFFER_SPAN);
-
- parse_inline(work, rndr, data + i, end - i);
-
- if (rndr->cb.header)
- rndr->cb.header(ob, work, (int)level, rndr->opaque);
-
- rndr_popbuf(rndr, BUFFER_SPAN);
- }
-
- return skip;
-}
-
-
-/* htmlblock_end • checking end of HTML block : </tag>[ \t]*\n[ \t*]\n */
-/* returns the length on match, 0 otherwise */
-static size_t
-htmlblock_end_tag(
- const char *tag,
- size_t tag_len,
- struct sd_markdown *rndr,
- uint8_t *data,
- size_t size)
-{
- size_t i, w;
-
- /* checking if tag is a match */
- if (tag_len + 3 >= size ||
- strncasecmp((char *)data + 2, tag, tag_len) != 0 ||
- data[tag_len + 2] != '>')
- return 0;
-
- /* checking white lines */
- i = tag_len + 3;
- w = 0;
- if (i < size && (w = is_empty(data + i, size - i)) == 0)
- return 0; /* non-blank after tag */
- i += w;
- w = 0;
-
- if (i < size)
- w = is_empty(data + i, size - i);
-
- return i + w;
-}
-
-static size_t
-htmlblock_end(const char *curtag,
- struct sd_markdown *rndr,
- uint8_t *data,
- size_t size,
- int start_of_line)
-{
- size_t tag_size = strlen(curtag);
- size_t i = 1, end_tag;
- int block_lines = 0;
-
- while (i < size) {
- i++;
- while (i < size && !(data[i - 1] == '<' && data[i] == '/')) {
- if (data[i] == '\n')
- block_lines++;
-
- i++;
- }
-
- /* If we are only looking for unindented tags, skip the tag
- * if it doesn't follow a newline.
- *
- * The only exception to this is if the tag is still on the
- * initial line; in that case it still counts as a closing
- * tag
- */
- if (start_of_line && block_lines > 0 && data[i - 2] != '\n')
- continue;
-
- if (i + 2 + tag_size >= size)
- break;
-
- end_tag = htmlblock_end_tag(curtag, tag_size, rndr, data + i - 1, size - i + 1);
- if (end_tag)
- return i + end_tag - 1;
- }
-
- return 0;
-}
-
-
-/* parse_htmlblock • parsing of inline HTML block */
-static size_t
-parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int do_render)
-{
- size_t i, j = 0, tag_end;
- const char *curtag = NULL;
- struct buf work = { data, 0, 0, 0 };
-
- /* identification of the opening tag */
- if (size < 2 || data[0] != '<')
- return 0;
-
- i = 1;
- while (i < size && data[i] != '>' && data[i] != ' ')
- i++;
-
- if (i < size)
- curtag = find_block_tag((char *)data + 1, (int)i - 1);
-
- /* handling of special cases */
- if (!curtag) {
-
- /* HTML comment, laxist form */
- if (size > 5 && data[1] == '!' && data[2] == '-' && data[3] == '-') {
- i = 5;
-
- while (i < size && !(data[i - 2] == '-' && data[i - 1] == '-' && data[i] == '>'))
- i++;
-
- i++;
-
- if (i < size)
- j = is_empty(data + i, size - i);
-
- if (j) {
- work.size = i + j;
- if (do_render && rndr->cb.blockhtml)
- rndr->cb.blockhtml(ob, &work, rndr->opaque);
- return work.size;
- }
- }
-
- /* HR, which is the only self-closing block tag considered */
- if (size > 4 && (data[1] == 'h' || data[1] == 'H') && (data[2] == 'r' || data[2] == 'R')) {
- i = 3;
- while (i < size && data[i] != '>')
- i++;
-
- if (i + 1 < size) {
- i++;
- j = is_empty(data + i, size - i);
- if (j) {
- work.size = i + j;
- if (do_render && rndr->cb.blockhtml)
- rndr->cb.blockhtml(ob, &work, rndr->opaque);
- return work.size;
- }
- }
- }
-
- /* no special case recognised */
- return 0;
- }
-
- /* looking for an unindented matching closing tag */
- /* followed by a blank line */
- tag_end = htmlblock_end(curtag, rndr, data, size, 1);
-
- /* if not found, trying a second pass looking for indented match */
- /* but not if tag is "ins" or "del" (following original Markdown.pl) */
- if (!tag_end && strcmp(curtag, "ins") != 0 && strcmp(curtag, "del") != 0) {
- tag_end = htmlblock_end(curtag, rndr, data, size, 0);
- }
-
- if (!tag_end)
- return 0;
-
- /* the end of the block has been found */
- work.size = tag_end;
- if (do_render && rndr->cb.blockhtml)
- rndr->cb.blockhtml(ob, &work, rndr->opaque);
-
- return tag_end;
-}
-
-static void
-parse_table_row(
- struct buf *ob,
- struct sd_markdown *rndr,
- uint8_t *data,
- size_t size,
- size_t columns,
- int *col_data,
- int header_flag)
-{
- size_t i = 0, col;
- struct buf *row_work = 0;
-
- if (!rndr->cb.table_cell || !rndr->cb.table_row)
- return;
-
- row_work = rndr_newbuf(rndr, BUFFER_SPAN);
-
- if (i < size && data[i] == '|')
- i++;
-
- for (col = 0; col < columns && i < size; ++col) {
- size_t cell_start, cell_end;
- struct buf *cell_work;
-
- cell_work = rndr_newbuf(rndr, BUFFER_SPAN);
-
- while (i < size && _isspace(data[i]))
- i++;
-
- cell_start = i;
-
- while (i < size && data[i] != '|')
- i++;
-
- cell_end = i - 1;
-
- while (cell_end > cell_start && _isspace(data[cell_end]))
- cell_end--;
-
- parse_inline(cell_work, rndr, data + cell_start, 1 + cell_end - cell_start);
- rndr->cb.table_cell(row_work, cell_work, col_data[col] | header_flag, rndr->opaque);
-
- rndr_popbuf(rndr, BUFFER_SPAN);
- i++;
- }
-
- for (; col < columns; ++col) {
- struct buf empty_cell = { 0, 0, 0, 0 };
- rndr->cb.table_cell(row_work, &empty_cell, col_data[col] | header_flag, rndr->opaque);
- }
-
- rndr->cb.table_row(ob, row_work, rndr->opaque);
-
- rndr_popbuf(rndr, BUFFER_SPAN);
-}
-
-static size_t
-parse_table_header(
- struct buf *ob,
- struct sd_markdown *rndr,
- uint8_t *data,
- size_t size,
- size_t *columns,
- int **column_data)
-{
- int pipes;
- size_t i = 0, col, header_end, under_end;
-
- pipes = 0;
- while (i < size && data[i] != '\n')
- if (data[i++] == '|')
- pipes++;
-
- if (i == size || pipes == 0)
- return 0;
-
- header_end = i;
-
- while (header_end > 0 && _isspace(data[header_end - 1]))
- header_end--;
-
- if (data[0] == '|')
- pipes--;
-
- if (header_end && data[header_end - 1] == '|')
- pipes--;
-
- *columns = pipes + 1;
- *column_data = calloc(*columns, sizeof(int));
-
- /* Parse the header underline */
- i++;
- if (i < size && data[i] == '|')
- i++;
-
- under_end = i;
- while (under_end < size && data[under_end] != '\n')
- under_end++;
-
- for (col = 0; col < *columns && i < under_end; ++col) {
- size_t dashes = 0;
-
- while (i < under_end && data[i] == ' ')
- i++;
-
- if (data[i] == ':') {
- i++; (*column_data)[col] |= MKD_TABLE_ALIGN_L;
- dashes++;
- }
-
- while (i < under_end && data[i] == '-') {
- i++; dashes++;
- }
-
- if (i < under_end && data[i] == ':') {
- i++; (*column_data)[col] |= MKD_TABLE_ALIGN_R;
- dashes++;
- }
-
- while (i < under_end && data[i] == ' ')
- i++;
-
- if (i < under_end && data[i] != '|')
- break;
-
- if (dashes < 3)
- break;
-
- i++;
- }
-
- if (col < *columns)
- return 0;
-
- parse_table_row(
- ob, rndr, data,
- header_end,
- *columns,
- *column_data,
- MKD_TABLE_HEADER
- );
-
- return under_end + 1;
-}
-
-static size_t
-parse_table(
- struct buf *ob,
- struct sd_markdown *rndr,
- uint8_t *data,
- size_t size)
-{
- size_t i;
-
- struct buf *header_work = 0;
- struct buf *body_work = 0;
-
- size_t columns;
- int *col_data = NULL;
-
- header_work = rndr_newbuf(rndr, BUFFER_SPAN);
- body_work = rndr_newbuf(rndr, BUFFER_BLOCK);
-
- i = parse_table_header(header_work, rndr, data, size, &columns, &col_data);
- if (i > 0) {
-
- while (i < size) {
- size_t row_start;
- int pipes = 0;
-
- row_start = i;
-
- while (i < size && data[i] != '\n')
- if (data[i++] == '|')
- pipes++;
-
- if (pipes == 0 || i == size) {
- i = row_start;
- break;
- }
-
- parse_table_row(
- body_work,
- rndr,
- data + row_start,
- i - row_start,
- columns,
- col_data, 0
- );
-
- i++;
- }
-
- if (rndr->cb.table)
- rndr->cb.table(ob, header_work, body_work, rndr->opaque);
- }
-
- free(col_data);
- rndr_popbuf(rndr, BUFFER_SPAN);
- rndr_popbuf(rndr, BUFFER_BLOCK);
- return i;
-}
-
-/* parse_block • parsing of one block, returning next uint8_t to parse */
-static void
-parse_block(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size)
-{
- size_t beg, end, i;
- uint8_t *txt_data;
- beg = 0;
-
- if (rndr->work_bufs[BUFFER_SPAN].size +
- rndr->work_bufs[BUFFER_BLOCK].size > rndr->max_nesting)
- return;
-
- while (beg < size) {
- txt_data = data + beg;
- end = size - beg;
-
- if (is_atxheader(rndr, txt_data, end))
- beg += parse_atxheader(ob, rndr, txt_data, end);
-
- else if (data[beg] == '<' && rndr->cb.blockhtml &&
- (i = parse_htmlblock(ob, rndr, txt_data, end, 1)) != 0)
- beg += i;
-
- else if ((i = is_empty(txt_data, end)) != 0)
- beg += i;
-
- else if (is_hrule(txt_data, end)) {
- if (rndr->cb.hrule)
- rndr->cb.hrule(ob, rndr->opaque);
-
- while (beg < size && data[beg] != '\n')
- beg++;
-
- beg++;
- }
-
- else if ((rndr->ext_flags & MKDEXT_FENCED_CODE) != 0 &&
- (i = parse_fencedcode(ob, rndr, txt_data, end)) != 0)
- beg += i;
-
- else if ((rndr->ext_flags & MKDEXT_TABLES) != 0 &&
- (i = parse_table(ob, rndr, txt_data, end)) != 0)
- beg += i;
-
- else if (prefix_quote(txt_data, end))
- beg += parse_blockquote(ob, rndr, txt_data, end);
-
- else if (prefix_code(txt_data, end))
- beg += parse_blockcode(ob, rndr, txt_data, end);
-
- else if (prefix_uli(txt_data, end))
- beg += parse_list(ob, rndr, txt_data, end, 0);
-
- else if (prefix_oli(txt_data, end))
- beg += parse_list(ob, rndr, txt_data, end, MKD_LIST_ORDERED);
-
- else
- beg += parse_paragraph(ob, rndr, txt_data, end);
- }
-}
-
-
-
-/*********************
- * REFERENCE PARSING *
- *********************/
-
-/* is_ref • returns whether a line is a reference or not */
-static int
-is_ref(const uint8_t *data, size_t beg, size_t end, size_t *last, struct link_ref **refs)
-{
-/* int n; */
- size_t i = 0;
- size_t id_offset, id_end;
- size_t link_offset, link_end;
- size_t title_offset, title_end;
- size_t line_end;
-
- /* up to 3 optional leading spaces */
- if (beg + 3 >= end) return 0;
- if (data[beg] == ' ') { i = 1;
- if (data[beg + 1] == ' ') { i = 2;
- if (data[beg + 2] == ' ') { i = 3;
- if (data[beg + 3] == ' ') return 0; } } }
- i += beg;
-
- /* id part: anything but a newline between brackets */
- if (data[i] != '[') return 0;
- i++;
- id_offset = i;
- while (i < end && data[i] != '\n' && data[i] != '\r' && data[i] != ']')
- i++;
- if (i >= end || data[i] != ']') return 0;
- id_end = i;
-
- /* spacer: colon (space | tab)* newline? (space | tab)* */
- i++;
- if (i >= end || data[i] != ':') return 0;
- i++;
- while (i < end && data[i] == ' ') i++;
- if (i < end && (data[i] == '\n' || data[i] == '\r')) {
- i++;
- if (i < end && data[i] == '\r' && data[i - 1] == '\n') i++; }
- while (i < end && data[i] == ' ') i++;
- if (i >= end) return 0;
-
- /* link: whitespace-free sequence, optionally between angle brackets */
- if (data[i] == '<')
- i++;
-
- link_offset = i;
-
- while (i < end && data[i] != ' ' && data[i] != '\n' && data[i] != '\r')
- i++;
-
- if (data[i - 1] == '>') link_end = i - 1;
- else link_end = i;
-
- /* optional spacer: (space | tab)* (newline | '\'' | '"' | '(' ) */
- while (i < end && data[i] == ' ') i++;
- if (i < end && data[i] != '\n' && data[i] != '\r'
- && data[i] != '\'' && data[i] != '"' && data[i] != '(')
- return 0;
- line_end = 0;
- /* computing end-of-line */
- if (i >= end || data[i] == '\r' || data[i] == '\n') line_end = i;
- if (i + 1 < end && data[i] == '\n' && data[i + 1] == '\r')
- line_end = i + 1;
-
- /* optional (space|tab)* spacer after a newline */
- if (line_end) {
- i = line_end + 1;
- while (i < end && data[i] == ' ') i++; }
-
- /* optional title: any non-newline sequence enclosed in '"()
- alone on its line */
- title_offset = title_end = 0;
- if (i + 1 < end
- && (data[i] == '\'' || data[i] == '"' || data[i] == '(')) {
- i++;
- title_offset = i;
- /* looking for EOL */
- while (i < end && data[i] != '\n' && data[i] != '\r') i++;
- if (i + 1 < end && data[i] == '\n' && data[i + 1] == '\r')
- title_end = i + 1;
- else title_end = i;
- /* stepping back */
- i -= 1;
- while (i > title_offset && data[i] == ' ')
- i -= 1;
- if (i > title_offset
- && (data[i] == '\'' || data[i] == '"' || data[i] == ')')) {
- line_end = title_end;
- title_end = i; } }
-
- if (!line_end || link_end == link_offset)
- return 0; /* garbage after the link empty link */
-
- /* a valid ref has been found, filling-in return structures */
- if (last)
- *last = line_end;
-
- if (refs) {
- struct link_ref *ref;
-
- ref = add_link_ref(refs, data + id_offset, id_end - id_offset);
- if (!ref)
- return 0;
-
- ref->link = bufnew(link_end - link_offset);
- bufput(ref->link, data + link_offset, link_end - link_offset);
-
- if (title_end > title_offset) {
- ref->title = bufnew(title_end - title_offset);
- bufput(ref->title, data + title_offset, title_end - title_offset);
- }
- }
-
- return 1;
-}
-
-static void expand_tabs(struct buf *ob, const uint8_t *line, size_t size)
-{
- size_t i = 0, tab = 0;
-
- while (i < size) {
- size_t org = i;
-
- while (i < size && line[i] != '\t') {
- i++; tab++;
- }
-
- if (i > org)
- bufput(ob, line + org, i - org);
-
- if (i >= size)
- break;
-
- do {
- bufputc(ob, ' '); tab++;
- } while (tab % 4);
-
- i++;
- }
-}
-
-/**********************
- * EXPORTED FUNCTIONS *
- **********************/
-
-struct sd_markdown *
-sd_markdown_new(
- unsigned int extensions,
- size_t max_nesting,
- const struct sd_callbacks *callbacks,
- void *opaque)
-{
- struct sd_markdown *md = NULL;
-
- assert(max_nesting > 0 && callbacks);
-
- md = malloc(sizeof(struct sd_markdown));
- if (!md)
- return NULL;
-
- memcpy(&md->cb, callbacks, sizeof(struct sd_callbacks));
-
- stack_init(&md->work_bufs[BUFFER_BLOCK], 4);
- stack_init(&md->work_bufs[BUFFER_SPAN], 8);
-
- memset(md->active_char, 0x0, 256);
-
- if (md->cb.emphasis || md->cb.double_emphasis || md->cb.triple_emphasis) {
- md->active_char['*'] = MD_CHAR_EMPHASIS;
- md->active_char['_'] = MD_CHAR_EMPHASIS;
- if (extensions & MKDEXT_STRIKETHROUGH)
- md->active_char['~'] = MD_CHAR_EMPHASIS;
- }
-
- if (md->cb.codespan)
- md->active_char['`'] = MD_CHAR_CODESPAN;
-
- if (md->cb.linebreak)
- md->active_char['\n'] = MD_CHAR_LINEBREAK;
-
- if (md->cb.image || md->cb.link)
- md->active_char['['] = MD_CHAR_LINK;
-
- md->active_char['<'] = MD_CHAR_LANGLE;
- md->active_char['\\'] = MD_CHAR_ESCAPE;
- md->active_char['&'] = MD_CHAR_ENTITITY;
-
- if (extensions & MKDEXT_AUTOLINK) {
- md->active_char[':'] = MD_CHAR_AUTOLINK_URL;
- md->active_char['@'] = MD_CHAR_AUTOLINK_EMAIL;
- md->active_char['w'] = MD_CHAR_AUTOLINK_WWW;
- }
-
- if (extensions & MKDEXT_SUPERSCRIPT)
- md->active_char['^'] = MD_CHAR_SUPERSCRIPT;
-
- /* Extension data */
- md->ext_flags = extensions;
- md->opaque = opaque;
- md->max_nesting = max_nesting;
- md->in_link_body = 0;
-
- return md;
-}
-
-void
-sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, struct sd_markdown *md)
-{
-#define MARKDOWN_GROW(x) ((x) + ((x) >> 1))
- static const char UTF8_BOM[] = {0xEF, 0xBB, 0xBF};
-
- struct buf *text;
- size_t beg, end;
-
- text = bufnew(64);
- if (!text)
- return;
-
- /* Preallocate enough space for our buffer to avoid expanding while copying */
- bufgrow(text, doc_size);
-
- /* reset the references table */
- memset(&md->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));
-
- /* first pass: looking for references, copying everything else */
- beg = 0;
-
- /* Skip a possible UTF-8 BOM, even though the Unicode standard
- * discourages having these in UTF-8 documents */
- if (doc_size >= 3 && memcmp(document, UTF8_BOM, 3) == 0)
- beg += 3;
-
- while (beg < doc_size) /* iterating over lines */
- if (is_ref(document, beg, doc_size, &end, md->refs))
- beg = end;
- else { /* skipping to the next line */
- end = beg;
- while (end < doc_size && document[end] != '\n' && document[end] != '\r')
- end++;
-
- /* adding the line body if present */
- if (end > beg)
- expand_tabs(text, document + beg, end - beg);
-
- while (end < doc_size && (document[end] == '\n' || document[end] == '\r')) {
- /* add one \n per newline */
- if (document[end] == '\n' || (end + 1 < doc_size && document[end + 1] != '\n'))
- bufputc(text, '\n');
- end++;
- }
-
- beg = end;
- }
-
- /* pre-grow the output buffer to minimize allocations */
- bufgrow(ob, MARKDOWN_GROW(text->size));
-
- /* second pass: actual rendering */
- if (md->cb.doc_header)
- md->cb.doc_header(ob, md->opaque);
-
- if (text->size) {
- /* adding a final newline if not already present */
- if (text->data[text->size - 1] != '\n' && text->data[text->size - 1] != '\r')
- bufputc(text, '\n');
-
- parse_block(ob, md, text->data, text->size);
- }
-
- if (md->cb.doc_footer)
- md->cb.doc_footer(ob, md->opaque);
-
- /* clean-up */
- bufrelease(text);
- free_link_refs(md->refs);
-
- assert(md->work_bufs[BUFFER_SPAN].size == 0);
- assert(md->work_bufs[BUFFER_BLOCK].size == 0);
-}
-
-void
-sd_markdown_free(struct sd_markdown *md)
-{
- size_t i;
-
- for (i = 0; i < (size_t)md->work_bufs[BUFFER_SPAN].asize; ++i)
- bufrelease(md->work_bufs[BUFFER_SPAN].item[i]);
-
- for (i = 0; i < (size_t)md->work_bufs[BUFFER_BLOCK].asize; ++i)
- bufrelease(md->work_bufs[BUFFER_BLOCK].item[i]);
-
- stack_free(&md->work_bufs[BUFFER_SPAN]);
- stack_free(&md->work_bufs[BUFFER_BLOCK]);
-
- free(md);
-}
-
-void
-sd_version(int *ver_major, int *ver_minor, int *ver_revision)
-{
- *ver_major = SUNDOWN_VER_MAJOR;
- *ver_minor = SUNDOWN_VER_MINOR;
- *ver_revision = SUNDOWN_VER_REVISION;
-}
-
-/* vim: set filetype=c: */
+++ /dev/null
-/* markdown.h - generic markdown parser */
-
-/*
- * Copyright (c) 2009, Natacha Porté
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef UPSKIRT_MARKDOWN_H
-#define UPSKIRT_MARKDOWN_H
-
-#include "buffer.h"
-#include "autolink.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SUNDOWN_VERSION "1.16.0"
-#define SUNDOWN_VER_MAJOR 1
-#define SUNDOWN_VER_MINOR 16
-#define SUNDOWN_VER_REVISION 0
-
-/********************
- * TYPE DEFINITIONS *
- ********************/
-
-/* mkd_autolink - type of autolink */
-enum mkd_autolink {
- MKDA_NOT_AUTOLINK, /* used internally when it is not an autolink*/
- MKDA_NORMAL, /* normal http/http/ftp/mailto/etc link */
- MKDA_EMAIL, /* e-mail link without explit mailto: */
-};
-
-enum mkd_tableflags {
- MKD_TABLE_ALIGN_L = 1,
- MKD_TABLE_ALIGN_R = 2,
- MKD_TABLE_ALIGN_CENTER = 3,
- MKD_TABLE_ALIGNMASK = 3,
- MKD_TABLE_HEADER = 4
-};
-
-enum mkd_extensions {
- MKDEXT_NO_INTRA_EMPHASIS = (1 << 0),
- MKDEXT_TABLES = (1 << 1),
- MKDEXT_FENCED_CODE = (1 << 2),
- MKDEXT_AUTOLINK = (1 << 3),
- MKDEXT_STRIKETHROUGH = (1 << 4),
- MKDEXT_SPACE_HEADERS = (1 << 6),
- MKDEXT_SUPERSCRIPT = (1 << 7),
- MKDEXT_LAX_SPACING = (1 << 8),
-};
-
-/* sd_callbacks - functions for rendering parsed data */
-struct sd_callbacks {
- /* block level callbacks - NULL skips the block */
- void (*blockcode)(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque);
- void (*blockquote)(struct buf *ob, const struct buf *text, void *opaque);
- void (*blockhtml)(struct buf *ob,const struct buf *text, void *opaque);
- void (*header)(struct buf *ob, const struct buf *text, int level, void *opaque);
- void (*hrule)(struct buf *ob, void *opaque);
- void (*list)(struct buf *ob, const struct buf *text, int flags, void *opaque);
- void (*listitem)(struct buf *ob, const struct buf *text, int flags, void *opaque);
- void (*paragraph)(struct buf *ob, const struct buf *text, void *opaque);
- void (*table)(struct buf *ob, const struct buf *header, const struct buf *body, void *opaque);
- void (*table_row)(struct buf *ob, const struct buf *text, void *opaque);
- void (*table_cell)(struct buf *ob, const struct buf *text, int flags, void *opaque);
-
-
- /* span level callbacks - NULL or return 0 prints the span verbatim */
- int (*autolink)(struct buf *ob, const struct buf *link, enum mkd_autolink type, void *opaque);
- int (*codespan)(struct buf *ob, const struct buf *text, void *opaque);
- int (*double_emphasis)(struct buf *ob, const struct buf *text, void *opaque);
- int (*emphasis)(struct buf *ob, const struct buf *text, void *opaque);
- int (*image)(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque);
- int (*linebreak)(struct buf *ob, void *opaque);
- int (*link)(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque);
- int (*raw_html_tag)(struct buf *ob, const struct buf *tag, void *opaque);
- int (*triple_emphasis)(struct buf *ob, const struct buf *text, void *opaque);
- int (*strikethrough)(struct buf *ob, const struct buf *text, void *opaque);
- int (*superscript)(struct buf *ob, const struct buf *text, void *opaque);
-
- /* low level callbacks - NULL copies input directly into the output */
- void (*entity)(struct buf *ob, const struct buf *entity, void *opaque);
- void (*normal_text)(struct buf *ob, const struct buf *text, void *opaque);
-
- /* header and footer */
- void (*doc_header)(struct buf *ob, void *opaque);
- void (*doc_footer)(struct buf *ob, void *opaque);
-};
-
-struct sd_markdown;
-
-/*********
- * FLAGS *
- *********/
-
-/* list/listitem flags */
-#define MKD_LIST_ORDERED 1
-#define MKD_LI_BLOCK 2 /* <li> containing block data */
-
-/**********************
- * EXPORTED FUNCTIONS *
- **********************/
-
-extern struct sd_markdown *
-sd_markdown_new(
- unsigned int extensions,
- size_t max_nesting,
- const struct sd_callbacks *callbacks,
- void *opaque);
-
-extern void
-sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, struct sd_markdown *md);
-
-extern void
-sd_markdown_free(struct sd_markdown *md);
-
-extern void
-sd_version(int *major, int *minor, int *revision);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-/* vim: set filetype=c: */
+++ /dev/null
-#include "stack.h"
-#include <string.h>
-
-int
-stack_grow(struct stack *st, size_t new_size)
-{
- void **new_st;
-
- if (st->asize >= new_size)
- return 0;
-
- new_st = realloc(st->item, new_size * sizeof(void *));
- if (new_st == NULL)
- return -1;
-
- memset(new_st + st->asize, 0x0,
- (new_size - st->asize) * sizeof(void *));
-
- st->item = new_st;
- st->asize = new_size;
-
- if (st->size > new_size)
- st->size = new_size;
-
- return 0;
-}
-
-void
-stack_free(struct stack *st)
-{
- if (!st)
- return;
-
- free(st->item);
-
- st->item = NULL;
- st->size = 0;
- st->asize = 0;
-}
-
-int
-stack_init(struct stack *st, size_t initial_size)
-{
- st->item = NULL;
- st->size = 0;
- st->asize = 0;
-
- if (!initial_size)
- initial_size = 8;
-
- return stack_grow(st, initial_size);
-}
-
-void *
-stack_pop(struct stack *st)
-{
- if (!st->size)
- return NULL;
-
- return st->item[--st->size];
-}
-
-int
-stack_push(struct stack *st, void *item)
-{
- if (stack_grow(st, st->size * 2) < 0)
- return -1;
-
- st->item[st->size++] = item;
- return 0;
-}
-
-void *
-stack_top(struct stack *st)
-{
- if (!st->size)
- return NULL;
-
- return st->item[st->size - 1];
-}
-
+++ /dev/null
-#ifndef STACK_H__
-#define STACK_H__
-
-#include <stdlib.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct stack {
- void **item;
- size_t size;
- size_t asize;
-};
-
-void stack_free(struct stack *);
-int stack_grow(struct stack *, size_t);
-int stack_init(struct stack *, size_t);
-
-int stack_push(struct stack *, void *);
-
-void *stack_pop(struct stack *);
-void *stack_top(struct stack *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
--- /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.
+
+// no-prefer-dynamic
+
+#![crate_type = "dylib"]
+
+extern crate a = "issue-12133-rlib";
+extern crate b = "issue-12133-dylib";
+
#![crate_id="a"]
#![crate_type = "lib"]
+
pub trait i<T> { }
-pub fn f<T>() -> ~i<T> {
+pub fn f<T>() -> Box<i<T>> {
impl<T> i<T> for () { }
- ~() as ~i<T>
+ box() () as Box<i<T>>
}
// Skipping ty_box
// Tests ty_uniq (of u8)
- pub type FooUniq = ~u8;
+ pub type FooUniq = Box<u8>;
// As with ty_str, what type should be used for ty_vec?
#[macro_registrar]
pub fn registrar(_: |Name, SyntaxExtension|) {
- local_data_key!(foo: ~Any:Send);
- local_data::set(foo, ~Foo { foo: 10 } as ~Any:Send);
+ local_data_key!(foo: Box<Any:Send>);
+ local_data::set(foo, box Foo { foo: 10 } as Box<Any:Send>);
}
#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
register(token::intern("make_a_1"),
- NormalTT(~BasicMacroExpander {
+ NormalTT(box BasicMacroExpander {
expander: expand_make_a_1,
span: None,
},
register(token::intern("into_foo"), ItemModifier(expand_into_foo));
}
-fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> ~MacResult {
+fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
+ -> Box<MacResult> {
if !tts.is_empty() {
cx.span_fatal(sp, "make_a_1 takes no arguments");
}
#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
register(token::intern("foo"),
- NormalTT(~BasicMacroExpander {
+ NormalTT(box BasicMacroExpander {
expander: expand_foo,
span: None,
},
None));
}
-fn expand_foo(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> ~MacResult {
+fn expand_foo(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
+ -> Box<MacResult> {
let answer = other::the_answer();
MacExpr::new(quote_expr!(cx, $answer))
}
let rdr = if os::getenv("RUST_BENCH").is_some() {
let foo = include_bin!("shootout-k-nucleotide.data");
- ~MemReader::new(Vec::from_slice(foo)) as ~Reader
+ box MemReader::new(Vec::from_slice(foo)) as Box<Reader>
} else {
- ~stdio::stdin() as ~Reader
+ box stdio::stdin() as Box<Reader>
};
let mut rdr = BufferedReader::new(rdr);
struct Entry {
code: Code,
count: uint,
- next: Option<~Entry>,
+ next: Option<Box<Entry>>,
}
struct Table {
count: uint,
- items: Vec<Option<~Entry>> }
+ items: Vec<Option<Box<Entry>>> }
struct Items<'a> {
cur: Option<&'a Entry>,
- items: slice::Items<'a, Option<~Entry>>,
+ items: slice::Items<'a, Option<Box<Entry>>>,
}
impl Table {
fn search_remainder<C:TableCallback>(item: &mut Entry, key: Code, c: C) {
match item.next {
None => {
- let mut entry = ~Entry {
+ let mut entry = box Entry {
code: key,
count: 0,
next: None,
{
if self.items.get(index as uint).is_none() {
- let mut entry = ~Entry {
+ let mut entry = box Entry {
code: key,
count: 0,
next: None,
fn main() {
let mut rdr = if std::os::getenv("RUST_BENCH").is_some() {
let fd = io::File::open(&Path::new("shootout-k-nucleotide.data"));
- ~io::BufferedReader::new(fd) as ~io::Reader
+ box io::BufferedReader::new(fd) as Box<io::Reader>
} else {
- ~io::stdin() as ~io::Reader
+ box io::stdin() as Box<io::Reader>
};
let mut seq = StrBuf::from_str(rdr.read_to_str().unwrap());
let ilen = seq.len();
use std::io;
use std::io::stdio::StdReader;
use std::io::BufferedReader;
-use std::os;
use std::num::Bitwise;
+use std::os;
// Computes a single solution to a given 9x9 sudoku
//
fn next_color(&mut self, row: u8, col: u8, start_color: u8) -> bool {
if start_color < 10u8 {
// colors not yet used
- let mut avail = ~Colors::new(start_color);
+ let mut avail = box Colors::new(start_color);
// drop colors already in use in neighbourhood
self.drop_colors(avail, row, col);
}
enum UniqueList {
- ULNil, ULCons(~UniqueList)
+ ULNil, ULCons(Box<UniqueList>)
}
fn main() {
struct State {
managed: @nillist,
- unique: ~nillist,
- tuple: (@nillist, ~nillist),
+ unique: Box<nillist>,
+ tuple: (@nillist, Box<nillist>),
vec: Vec<@nillist>,
res: r
}
None => {
State {
managed: @Nil,
- unique: ~Nil,
- tuple: (@Nil, ~Nil),
+ unique: box Nil,
+ tuple: (@Nil, box Nil),
vec: vec!(@Nil),
res: r(@Nil)
}
Some(st) => {
State {
managed: @Cons((), st.managed),
- unique: ~Cons((), @*st.unique),
+ unique: box Cons((), @*st.unique),
tuple: (@Cons((), st.tuple.ref0().clone()),
- ~Cons((), @*st.tuple.ref1().clone())),
+ box Cons((), @*st.tuple.ref1().clone())),
vec: st.vec.clone().append(&[@Cons((), *st.vec.last().unwrap())]),
res: r(@Cons((), st.res._l))
}
// Test that we detect nested calls that could free pointers evaluated
// for earlier arguments.
-fn rewrite(v: &mut ~uint) -> uint {
- *v = ~22;
+
+fn rewrite(v: &mut Box<uint>) -> uint {
+ *v = box 22;
**v
}
}
fn implicit() {
- let mut a = ~1;
+ let mut a = box 1;
// Note the danger here:
//
}
fn explicit() {
- let mut a = ~1;
+ let mut a = box 1;
add(
&*a,
rewrite(&mut a)); //~ ERROR cannot borrow
// Test that we detect nested calls that could free pointers evaluated
// for earlier arguments.
-fn rewrite(v: &mut ~uint) -> uint {
- *v = ~22;
+
+fn rewrite(v: &mut Box<uint>) -> uint {
+ *v = box 22;
**v
}
-fn add(v: &uint, w: ~uint) -> uint {
+fn add(v: &uint, w: Box<uint>) -> uint {
*v + *w
}
fn implicit() {
- let mut a = ~1;
+ let mut a = box 1;
// Note the danger here:
//
}
fn explicit() {
- let mut a = ~1;
+ let mut a = box 1;
add(
&*a,
a); //~ ERROR cannot move
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct Foo {
bar1: Bar,
bar2: Bar
int2: int,
}
-fn make_foo() -> ~Foo { fail!() }
+fn make_foo() -> Box<Foo> { fail!() }
fn borrow_same_field_twice_mut_mut() {
let mut foo = make_foo();
}
fn deref_extend_mut_field3<'a>(x: &'a mut Own<Point>) {
- // Hmm, this is unfortunate, because with ~ it would work,
+ // Hmm, this is unfortunate, because with box it would work,
// but it's presently the expected outcome. See `deref_extend_mut_field4`
// for the workaround.
fn main() {
let mut buggy_map: HashMap<uint, &uint> = HashMap::new();
- buggy_map.insert(42, &*~1); //~ ERROR borrowed value does not live long enough
+ buggy_map.insert(42, &*box 1); //~ ERROR borrowed value does not live long enough
// but it is ok if we use a temporary
- let tmp = ~2;
+ let tmp = box 2;
buggy_map.insert(43, &*tmp);
}
// Tests that two closures cannot simultaneously have mutable
// and immutable access to the variable. Issue #6801.
+
fn get(x: &int) -> int {
*x
}
}
fn f() {
- let mut x = ~3;
+ let mut x = box 3;
let c1 = || get(&*x);
*x = 5; //~ ERROR cannot assign
}
fn g() {
struct Foo {
- f: ~int
+ f: Box<int>
}
- let mut x = ~Foo { f: ~3 };
+ let mut x = box Foo { f: box 3 };
let c1 = || get(&*x.f);
*x.f = 5; //~ ERROR cannot assign to `*x.f`
}
fn h() {
struct Foo {
- f: ~int
+ f: Box<int>
}
- let mut x = ~Foo { f: ~3 };
+ let mut x = box Foo { f: box 3 };
let c1 = || get(&*x.f);
let c2 = || *x.f = 5; //~ ERROR cannot borrow `x` as mutable
}
// access to the variable, whether that mutable access be used
// for direct assignment or for taking mutable ref. Issue #6801.
+
fn a() {
let mut x = 3;
let c1 = || x = 4;
fn g() {
struct Foo {
- f: ~int
+ f: Box<int>
}
- let mut x = ~Foo { f: ~3 };
+ let mut x = box Foo { f: box 3 };
let c1 = || set(&mut *x.f);
let c2 = || set(&mut *x.f);
//~^ ERROR cannot borrow `x` as mutable more than once
// cannot also be supplied a borrowed version of that
// variable's contents. Issue #11192.
+
struct Foo {
x: int
}
}
fn main() {
- let mut ptr = ~Foo { x: 0 };
+ let mut ptr = box Foo { x: 0 };
let test = |foo: &Foo| {
- ptr = ~Foo { x: ptr.x + 1 };
+ ptr = box Foo { x: ptr.x + 1 };
};
test(ptr); //~ ERROR cannot borrow `*ptr`
}
// except according to those terms.
fn main() {
-let x = Some(~1);
+let x = Some(box 1);
match x {
Some(ref _y) => {
let _a = x; //~ ERROR cannot move
// except according to those terms.
fn main() {
-let x = Some(~1);
+let x = Some(box 1);
match x {
Some(ref y) => {
let _b = *y; //~ ERROR cannot move out
// either genuine or would require more advanced changes. The latter
// cases are noted.
+
fn borrow(_v: &int) {}
fn borrow_mut(_v: &mut int) {}
fn cond() -> bool { fail!() }
fn for_func(_f: || -> bool) { fail!() }
fn produce<T>() -> T { fail!(); }
-fn inc(v: &mut ~int) {
- *v = ~(**v + 1);
+fn inc(v: &mut Box<int>) {
+ *v = box() (**v + 1);
}
fn pre_freeze_cond() {
// In this instance, the freeze is conditional and starts before
// the mut borrow.
- let mut v = ~3;
+ let mut v = box 3;
let _w;
if cond() {
_w = &v;
// In this instance, the freeze and mut borrow are on separate sides
// of the if.
- let mut v = ~3;
+ let mut v = box 3;
let _w;
if cond() {
_w = &v;
// either genuine or would require more advanced changes. The latter
// cases are noted.
+
fn borrow(_v: &int) {}
fn borrow_mut(_v: &mut int) {}
fn cond() -> bool { fail!() }
fn produce<T>() -> T { fail!(); }
-fn inc(v: &mut ~int) {
- *v = ~(**v + 1);
+fn inc(v: &mut Box<int>) {
+ *v = box() (**v + 1);
}
fn loop_overarching_alias_mut() {
// In this instance, the borrow encompasses the entire loop.
- let mut v = ~3;
+ let mut v = box 3;
let mut x = &mut v;
**x += 1;
loop {
fn block_overarching_alias_mut() {
// In this instance, the borrow encompasses the entire closure call.
- let mut v = ~3;
+ let mut v = box 3;
let mut x = &mut v;
for _ in range(0, 3) {
borrow(v); //~ ERROR cannot borrow
}
- *x = ~5;
+ *x = box 5;
}
fn loop_aliased_mut() {
// In this instance, the borrow is carried through the loop.
- let mut v = ~3;
- let mut w = ~4;
+ let mut v = box 3;
+ let mut w = box 4;
let mut _x = &w;
loop {
borrow_mut(v); //~ ERROR cannot borrow
fn while_aliased_mut() {
// In this instance, the borrow is carried through the loop.
- let mut v = ~3;
- let mut w = ~4;
+ let mut v = box 3;
+ let mut w = box 4;
let mut _x = &w;
while cond() {
borrow_mut(v); //~ ERROR cannot borrow
fn loop_aliased_mut_break() {
// In this instance, the borrow is carried through the loop.
- let mut v = ~3;
- let mut w = ~4;
+ let mut v = box 3;
+ let mut w = box 4;
let mut _x = &w;
loop {
borrow_mut(v);
fn while_aliased_mut_break() {
// In this instance, the borrow is carried through the loop.
- let mut v = ~3;
- let mut w = ~4;
+ let mut v = box 3;
+ let mut w = box 4;
let mut _x = &w;
while cond() {
borrow_mut(v);
}
fn while_aliased_mut_cond(cond: bool, cond2: bool) {
- let mut v = ~3;
- let mut w = ~4;
+ let mut v = box 3;
+ let mut w = box 4;
let mut x = &mut w;
while cond {
**x += 1;
// Here the guard performs a borrow. This borrow "infects" all
// subsequent arms (but not the prior ones).
- let mut a = ~3;
- let mut b = ~4;
+ let mut a = box 3;
+ let mut b = box 4;
let mut w = &*a;
match 22 {
_ if cond() => {
- b = ~5;
+ b = box 5;
}
_ if link(&*b, &mut w) => {
- b = ~6; //~ ERROR cannot assign
+ b = box 6; //~ ERROR cannot assign
}
_ => {
- b = ~7; //~ ERROR cannot assign
+ b = box 7; //~ ERROR cannot assign
}
}
- b = ~8; //~ ERROR cannot assign
+ b = box 8; //~ ERROR cannot assign
}
fn main() {}
// either genuine or would require more advanced changes. The latter
// cases are noted.
+
fn borrow(_v: &int) {}
fn borrow_mut(_v: &mut int) {}
fn cond() -> bool { fail!() }
fn for_func(_f: || -> bool) { fail!() }
fn produce<T>() -> T { fail!(); }
-fn inc(v: &mut ~int) {
- *v = ~(**v + 1);
+fn inc(v: &mut Box<int>) {
+ *v = box() (**v + 1);
}
fn pre_freeze() {
// In this instance, the freeze starts before the mut borrow.
- let mut v = ~3;
+ let mut v = box 3;
let _w = &v;
borrow_mut(v); //~ ERROR cannot borrow
}
fn post_freeze() {
// In this instance, the const alias starts after the borrow.
- let mut v = ~3;
+ let mut v = box 3;
borrow_mut(v);
let _w = &v;
}
}
fn box_imm() {
- let v = ~3;
+ let v = box 3;
let _w = &v;
task::spawn(proc() {
println!("v={}", *v);
}
fn box_imm_explicit() {
- let v = ~3;
+ let v = box 3;
let _w = &v;
task::spawn(proc() {
println!("v={}", *v);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn take(_v: ~int) {
+
+fn take(_v: Box<int>) {
}
fn box_imm() {
- let v = ~3;
+ let v = box 3;
let _w = &v;
take(v); //~ ERROR cannot move out of `v` because it is borrowed
}
}
fn box_imm() {
- let mut v = ~3;
+ let mut v = box 3;
borrow(v,
|w| { //~ ERROR cannot borrow `v` as mutable
- v = ~4;
+ v = box 4;
assert_eq!(*v, 3);
assert_eq!(*w, 4);
})
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-struct foo(~uint);
+
+struct foo(Box<uint>);
impl Add<foo, foo> for foo {
fn add(&self, f: &foo) -> foo {
- let foo(~i) = *self;
- let foo(~j) = *f;
- foo(~(i + j))
+ let foo(box i) = *self;
+ let foo(box j) = *f;
+ foo(box() (i + j))
}
}
fn main() {
- let x = foo(~3);
+ let x = foo(box 3);
let _y = x + {x}; // the `{x}` forces a move to occur
//~^ ERROR cannot move out of `x`
}
// except according to those terms.
pub fn main() {
- let bar = ~3;
+ let bar = box 3;
let _g = || {
let _h: proc() -> int = proc() *bar; //~ ERROR cannot move out of captured outer variable
};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
enum Foo {
- Foo1(~u32, ~u32),
- Foo2(~u32),
+ Foo1(Box<u32>, Box<u32>),
+ Foo2(Box<u32>),
Foo3,
}
fn blah() {
- let f = &Foo1(~1u32, ~2u32);
+ let f = &Foo1(box 1u32, box 2u32);
match *f { //~ ERROR cannot move out of
Foo1(num1, //~ NOTE attempting to move value to here
num2) => (), //~ NOTE and here
}
}
-struct S {f:~str, g:~str}
+struct S {
+ f: ~str,
+ g: ~str
+}
impl Drop for S {
fn drop(&mut self) { println!("{}", self.f); }
}
// from issue-8064
struct A {
- a: ~int
+ a: Box<int>,
}
fn free<T>(_: T) {}
fn blah2() {
- let a = &A { a: ~1 };
+ let a = &A { a: box 1 };
match a.a { //~ ERROR cannot move out of
n => { //~ NOTE attempting to move value to here
free(n)
// borrowed path.
fn main() {
- let a = ~~2;
+ let a = box box 2;
let b = &a;
let z = *a; //~ ERROR: cannot move out of `*a` because it is borrowed
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn foo(x: *~int) -> ~int {
+
+fn foo(x: *Box<int>) -> Box<int> {
let y = *x; //~ ERROR dereference of unsafe pointer requires unsafe function or block
return y;
}
}
fn main() {
- let t = ~3;
+ let t = box 3;
call_f(proc() { *t + 1 });
call_f(proc() { *t + 1 }); //~ ERROR capture of moved value
// Tests that the borrow checker checks all components of a path when moving
// out.
-#![no_std]
-
-#[lang="sized"]
-pub trait Sized {}
struct S {
- x : ~int
+ x : Box<int>
}
fn f<T>(_: T) {}
fn main() {
- let a : S = S { x : ~1 };
+ let a : S = S { x : box 1 };
let pb = &a;
let S { x: ax } = a; //~ ERROR cannot move out
f(pb);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct node_ {
- a: ~cycle
+ a: Box<cycle>
}
enum cycle {
empty
}
fn main() {
- let mut x = ~node(node_ {a: ~empty});
+ let mut x = box node(node_ {a: box empty});
// Create a cycle!
match *x {
node(ref mut y) => {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait Foo {
fn borrowed<'a>(&'a self) -> &'a ();
}
x.borrowed()
}
-fn owned_receiver(x: ~Foo) -> &() {
+fn owned_receiver(x: Box<Foo>) -> &() {
x.borrowed() //~ ERROR `*x` does not live long enough
}
-fn mut_owned_receiver(mut x: ~Foo) {
+fn mut_owned_receiver(mut x: Box<Foo>) {
let _y = x.borrowed();
let _z = &mut x; //~ ERROR cannot borrow
}
-fn imm_owned_receiver(mut x: ~Foo) {
+fn imm_owned_receiver(mut x: Box<Foo>) {
let _y = x.borrowed();
let _z = &x;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait Foo {
fn borrowed(&self);
fn borrowed_mut(&mut self);
x.borrowed_mut();
}
-fn owned_receiver(x: ~Foo) {
+fn owned_receiver(x: Box<Foo>) {
x.borrowed();
x.borrowed_mut(); //~ ERROR cannot borrow
}
-fn mut_owned_receiver(mut x: ~Foo) {
+fn mut_owned_receiver(mut x: Box<Foo>) {
x.borrowed();
x.borrowed_mut();
}
#![feature(managed_boxes)]
+
fn borrow(x: &int, f: |x: &int|) {
let before = *x;
f(x);
assert_eq!(before, after);
}
-struct F { f: ~int }
+struct F { f: Box<int> }
pub fn main() {
- let mut x = @F {f: ~3};
+ let mut x = @F {f: box 3};
borrow(x.f, |b_x| {
//~^ ERROR cannot borrow `x` as mutable because `*x.f` is also borrowed as immutable
assert_eq!(*b_x, 3);
assert_eq!(&(*x.f) as *int, &(*b_x) as *int);
//~^ NOTE borrow occurs due to use of `x` in closure
- x = @F {f: ~4};
+ x = @F {f: box 4};
println!("&*b_x = {:p}", &(*b_x));
assert_eq!(*b_x, 3);
#![feature(managed_boxes)]
+
fn borrow(x: &int, f: |x: &int|) {
let before = *x;
f(x);
assert_eq!(before, after);
}
-struct F { f: ~int }
+struct F { f: Box<int> }
pub fn main() {
- let mut x = ~@F{f: ~3};
+ let mut x = box @F{f: box 3};
borrow(x.f, |b_x| {
//~^ ERROR cannot borrow `x` as mutable because `*x.f` is also borrowed as immutable
assert_eq!(*b_x, 3);
assert_eq!(&(*x.f) as *int, &(*b_x) as *int);
//~^ NOTE borrow occurs due to use of `x` in closure
- *x = @F{f: ~4};
+ *x = @F{f: box 4};
println!("&*b_x = {:p}", &(*b_x));
assert_eq!(*b_x, 3);
#![feature(managed_boxes)]
+
fn borrow(x: &int, f: |x: &int|) {
let before = *x;
f(x);
assert_eq!(before, after);
}
-struct F { f: ~int }
+struct F { f: Box<int> }
pub fn main() {
- let mut x = @F {f: ~3};
+ let mut x = @F {f: box 3};
borrow((*x).f, |b_x| {
//~^ ERROR cannot borrow `x` as mutable because `*x.f` is also borrowed as immutable
assert_eq!(*b_x, 3);
assert_eq!(&(*x.f) as *int, &(*b_x) as *int);
//~^ NOTE borrow occurs due to use of `x` in closure
- x = @F {f: ~4};
+ x = @F {f: box 4};
println!("&*b_x = {:p}", &(*b_x));
assert_eq!(*b_x, 3);
// NoCopy
use NP = std::kinds::marker::NoCopy;
+
+
struct S { a: int, np: NP }
impl Drop for S { fn drop(&mut self) { } }
-struct T { a: int, mv: ~int }
+struct T { a: int, mv: Box<int> }
impl Drop for T { fn drop(&mut self) { } }
fn f(s0:S) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn foo(x: ~int) -> int {
+
+fn foo(x: Box<int>) -> int {
let y = &*x;
free(x); //~ ERROR cannot move out of `x` because it is borrowed
*y
}
-fn free(_x: ~int) {
+fn free(_x: Box<int>) {
}
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
fn borrow(_v: &int) {}
fn local() {
- let mut v = ~3;
+ let mut v = box 3;
borrow(v);
}
fn local_rec() {
- struct F { f: ~int }
- let mut v = F {f: ~3};
+ struct F { f: Box<int> }
+ let mut v = F {f: box 3};
borrow(v.f);
}
fn local_recs() {
struct F { f: G }
struct G { g: H }
- struct H { h: ~int }
- let mut v = F {f: G {g: H {h: ~3}}};
+ struct H { h: Box<int> }
+ let mut v = F {f: G {g: H {h: box 3}}};
borrow(v.f.g.h);
}
fn aliased_imm() {
- let mut v = ~3;
+ let mut v = box 3;
let _w = &v;
borrow(v);
}
fn aliased_mut() {
- let mut v = ~3;
+ let mut v = box 3;
let _w = &mut v;
borrow(v); //~ ERROR cannot borrow `*v`
}
fn aliased_other() {
- let mut v = ~3;
- let mut w = ~4;
+ let mut v = box 3;
+ let mut w = box 4;
let _x = &mut w;
borrow(v);
}
fn aliased_other_reassign() {
- let mut v = ~3;
- let mut w = ~4;
+ let mut v = box 3;
+ let mut w = box 4;
let mut _x = &mut w;
_x = &mut v;
borrow(v); //~ ERROR cannot borrow `*v`
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
fn a() {
- let mut vec = [~1, ~2, ~3];
+ let mut vec = [box 1, box 2, box 3];
match vec {
- [~ref _a, _, _] => {
- vec[0] = ~4; //~ ERROR cannot assign
+ [box ref _a, _, _] => {
+ vec[0] = box 4; //~ ERROR cannot assign
}
}
}
fn b() {
- let mut vec = vec!(~1, ~2, ~3);
- let vec: &mut [~int] = vec.as_mut_slice();
+ let mut vec = vec!(box 1, box 2, box 3);
+ let vec: &mut [Box<int>] = vec.as_mut_slice();
match vec {
[.._b] => {
- vec[0] = ~4; //~ ERROR cannot assign
+ vec[0] = box 4; //~ ERROR cannot assign
}
}
}
fn c() {
- let mut vec = vec!(~1, ~2, ~3);
- let vec: &mut [~int] = vec.as_mut_slice();
+ let mut vec = vec!(box 1, box 2, box 3);
+ let vec: &mut [Box<int>] = vec.as_mut_slice();
match vec {
[_a, //~ ERROR cannot move out
.._b] => { //~^ NOTE attempting to move value to here
}
fn d() {
- let mut vec = vec!(~1, ~2, ~3);
- let vec: &mut [~int] = vec.as_mut_slice();
+ let mut vec = vec!(box 1, box 2, box 3);
+ let vec: &mut [Box<int>] = vec.as_mut_slice();
match vec {
[.._a, //~ ERROR cannot move out
_b] => {} //~ NOTE attempting to move value to here
}
fn e() {
- let mut vec = vec!(~1, ~2, ~3);
- let vec: &mut [~int] = vec.as_mut_slice();
+ let mut vec = vec!(box 1, box 2, box 3);
+ let vec: &mut [Box<int>] = vec.as_mut_slice();
match vec {
[_a, _b, _c] => {} //~ ERROR cannot move out
//~^ NOTE attempting to move value to here
struct MyOwned;
-static STATIC11: ~MyOwned = ~MyOwned;
+static STATIC11: Box<MyOwned> = box MyOwned;
//~^ ERROR static items are not allowed to have owned pointers
// The following examples test that mutable structs are just forbidden
static mut STATIC14: SafeStruct = SafeStruct{field1: Variant1, field2: Variant4("str".to_owned())};
//~^ ERROR mutable static items are not allowed to have destructors
-static STATIC15: &'static [~MyOwned] = &'static [~MyOwned, ~MyOwned];
+static STATIC15: &'static [Box<MyOwned>] = &'static [box MyOwned, box MyOwned];
//~^ ERROR static items are not allowed to have owned pointers
//~^^ ERROR static items are not allowed to have owned pointers
-static STATIC16: (&'static ~MyOwned, &'static ~MyOwned) = (&'static ~MyOwned, &'static ~MyOwned);
+static STATIC16: (&'static Box<MyOwned>, &'static Box<MyOwned>) =
+ (&'static box MyOwned, &'static box MyOwned);
//~^ ERROR static items are not allowed to have owned pointers
//~^^ ERROR static items are not allowed to have owned pointers
static STATIC18: @SafeStruct = @SafeStruct{field1: Variant1, field2: Variant2(0)};
//~^ ERROR static items are not allowed to have managed pointers
-static STATIC19: ~int = box 3;
+static STATIC19: Box<int> = box 3;
//~^ ERROR static items are not allowed to have owned pointers
pub fn main() {
- let y = { static x: ~int = ~3; x };
+ let y = { static x: Box<int> = box 3; x };
//~^ ERROR static items are not allowed to have owned pointers
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait noisy {
fn speak(&self);
}
}
fn main() {
- let nyan: ~noisy = ~cat(0, 2, "nyan".to_owned()) as ~noisy;
+ let nyan: Box<noisy> = box cat(0, 2, "nyan".to_owned()) as Box<noisy>;
nyan.eat(); //~ ERROR does not implement any method in scope named `eat`
}
}
fn has_slice(x: &str) {
- wants_uniq(x); //~ ERROR mismatched types: expected `~str` but found `&str` (expected ~-ptr but f
+ wants_uniq(x); //~ ERROR mismatched types: expected `~str` but found `&str` (expected box but f
wants_slice(x);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn f(y: ~int) {
+
+fn f(y: Box<int>) {
*y = 5; //~ ERROR cannot assign
}
fn g() {
- let _frob: |~int| = |q| { *q = 2; }; //~ ERROR cannot assign
+ let _frob: |Box<int>| = |q| { *q = 2; }; //~ ERROR cannot assign
}
pub fn main() {
let mut x;
loop {
- x = ~x;
+ x = box x;
x.foo;
x.bar();
}
// Test struct inheritance.
#![feature(struct_inherit)]
-struct S6 : ~S2; //~ ERROR not a struct
+
+struct S6 : int; //~ ERROR super-struct could not be resolved
pub fn main() {
}
// except according to those terms.
fn main() {
- let x = ~1;
+ let x = box 1;
let f: proc() = proc() {
let _a = x;
drop(x);
}
fn main() {
- let mut ptr = ~Foo { x: 0 };
+ let mut ptr = box Foo { x: 0 };
let test = |foo: &Foo| {
println!("access {}", foo.x);
- ptr = ~Foo { x: ptr.x + 1 };
+ ptr = box Foo { x: ptr.x + 1 };
println!("access {}", foo.x);
};
test(ptr);
}
fn main() {
- let test = ~Test { func: proc() {} };
+ let test = box Test { func: proc() {} };
//~^ ERROR: expected `||` but found `proc()`
}
fn main() {
let r = {
- let x = ~42;
+ let x = box 42;
let f = proc() &x; //~ ERROR: `x` does not live long enough
f()
};
+++ /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.
-
-// aux-build:issue-12133-rlib.rs
-// aux-build:issue-12133-dylib.rs
-
-// error-pattern: dynamic linking is preferred, but dependencies were not found
-
-extern crate a = "issue-12133-rlib";
-extern crate b = "issue-12133-dylib";
-
-fn main() {}
+++ /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.
-
-// aux-build:issue-12133-rlib.rs
-// aux-build:issue-12133-dylib.rs
-// no-prefer-dynamic
-
-// error-pattern: dependencies were not all found in either dylib or rlib format
-
-extern crate a = "issue-12133-rlib";
-extern crate b = "issue-12133-dylib";
-
-fn main() {}
+++ /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.
-
-// aux-build:issue-12133-rlib.rs
-// aux-build:issue-12133-dylib.rs
-// no-prefer-dynamic
-
-// error-pattern: dylib output requested, but some depenencies could not
-
-#![crate_type = "dylib"]
-
-extern crate a = "issue-12133-rlib";
-extern crate b = "issue-12133-dylib";
// test that autoderef of a type like this does not
// cause compiler to loop. Note that no instances
// of such a type could ever be constructed.
-struct t(~t); //~ ERROR this type cannot be instantiated
+
+
+struct t(Box<t>); //~ ERROR this type cannot be instantiated
trait to_str_2 {
fn my_to_str() -> ~str;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct HTMLImageData {
image: Option<~str>
}
struct ElementData {
- kind: ~ElementKind
+ kind: Box<ElementKind>
}
enum ElementKind {
}
struct NodeData {
- kind: ~NodeKind
+ kind: Box<NodeKind>,
}
fn main() {
let mut id = HTMLImageData { image: None };
- let ed = ElementData { kind: ~HTMLImageElement(id) };
- let n = NodeData {kind : ~Element(ed)};
+ let ed = ElementData { kind: box HTMLImageElement(id) };
+ let n = NodeData {kind : box Element(ed)};
// n.b. span could be better
match n.kind {
- ~Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns
- ~HTMLImageElement(ref d) if d.image.is_some() => { true }
+ box Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns
+ box HTMLImageElement(ref d) if d.image.is_some() => { true }
},
_ => fail!("WAT") //~ ERROR unreachable pattern
};
let my_struct = my_mod::MyStruct();
let _woohoo = (&my_struct).priv_field;
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
- let _woohoo = (~my_struct).priv_field;
+ let _woohoo = (box my_struct).priv_field;
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
let _woohoo = (@my_struct).priv_field;
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
(&my_struct).happyfun(); //~ ERROR method `happyfun` is private
- (~my_struct).happyfun(); //~ ERROR method `happyfun` is private
+ (box my_struct).happyfun(); //~ ERROR method `happyfun` is private
(@my_struct).happyfun(); //~ ERROR method `happyfun` is private
let nope = my_struct.priv_field;
//~^ ERROR field `priv_field` of struct `my_mod::MyStruct` is private
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait MyTrait { }
pub enum TraitWrapper {
- A(~MyTrait),
+ A(Box<MyTrait>),
}
fn get_tw_map<'lt>(tw: &'lt TraitWrapper) -> &'lt MyTrait {
match *tw {
- A(~ref map) => map, //~ ERROR found a `~`-box pattern
+ A(box ref map) => map, //~ ERROR found a box pattern
}
}
}
match (true, false) {
- ~(true, false) => ()
- //~^ ERROR mismatched types: expected `(bool,bool)` but found a `~`-box pattern
+ box (true, false) => ()
+ //~^ ERROR mismatched types: expected `(bool,bool)` but found a box pattern
}
match (true, false) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct Foo {
foo: int,
}
}
impl Bar {
- fn make_foo (&self, i: int) -> ~Foo {
- return ~Foo { nonexistent: self, foo: i }; //~ ERROR: no field named
+ fn make_foo (&self, i: int) -> Box<Foo> {
+ return box Foo { nonexistent: self, foo: i }; //~ ERROR: no field named
}
}
// transferring ownership of the owned box before invoking the stack
// closure results in a crash.
-fn twice(x: ~uint) -> uint {
+
+fn twice(x: Box<uint>) -> uint {
*x * 2
}
}
fn main() {
- let x : ~uint = ~9;
+ let x : Box<uint> = box 9;
let sq : || -> uint = || { *x * *x };
twice(x); //~ ERROR: cannot move out of
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::rc::Rc;
use std::cell::RefCell;
+use std::rc::Rc;
-trait Foo
-{
+trait Foo {
fn set(&mut self, v: Rc<RefCell<A>>);
}
-struct B
-{
+struct B {
v: Option<Rc<RefCell<A>>>
}
-impl Foo for B
-{
+impl Foo for B {
fn set(&mut self, v: Rc<RefCell<A>>)
{
self.v = Some(v);
}
}
-struct A
-{
- v: ~Foo:Send,
+struct A {
+ v: Box<Foo:Send>,
}
-fn main()
-{
- let a = A {v: ~B{v: None} as ~Foo:Send};
+fn main() {
+ let a = A {v: box B{v: None} as Box<Foo:Send>};
//~^ ERROR cannot pack type `~B`, which does not fulfill `Send`
let v = Rc::new(RefCell::new(a));
let w = v.clone();
// Verify the compiler fails with an error on infinite function
// recursions.
-struct Data(~Option<Data>);
+
+struct Data(Box<Option<Data>>);
fn generic<T>( _ : Vec<(Data,T)> ) {
//~^ ERROR reached the recursion limit during monomorphization
}
struct MyNoncopyStruct {
- x: ~int,
+ x: Box<int>,
}
fn test<'a,T,U:Copy>(_: &'a int) {
assert_copy::<&'a mut int>(); //~ ERROR does not fulfill
// ~ pointers are not ok
- assert_copy::<~int>(); //~ ERROR does not fulfill
+ assert_copy::<Box<int>>(); //~ ERROR does not fulfill
assert_copy::<~str>(); //~ ERROR does not fulfill
assert_copy::<Vec<int> >(); //~ ERROR does not fulfill
- assert_copy::<~&'a mut int>(); //~ ERROR does not fulfill
+ assert_copy::<Box<&'a mut int>>(); //~ ERROR does not fulfill
// borrowed object types are generally ok
assert_copy::<&'a Dummy>();
assert_copy::<&'static Dummy:Copy>();
// owned object types are not ok
- assert_copy::<~Dummy>(); //~ ERROR does not fulfill
- assert_copy::<~Dummy:Copy>(); //~ ERROR does not fulfill
+ assert_copy::<Box<Dummy>>(); //~ ERROR does not fulfill
+ assert_copy::<Box<Dummy:Copy>>(); //~ ERROR does not fulfill
// mutable object types are not ok
assert_copy::<&'a mut Dummy:Copy>(); //~ ERROR does not fulfill
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait Repeat<A> { fn get(&self) -> A; }
impl<A:Clone> Repeat<A> for A {
fn get(&self) -> A { self.clone() }
}
-fn repeater<A:Clone>(v: A) -> ~Repeat<A>: {
- ~v as ~Repeat<A>: // No
+fn repeater<A:Clone>(v: A) -> Box<Repeat<A>:> {
+ box v as Box<Repeat<A>:> // No
}
fn main() {
assert_send::<&'a str>(); //~ ERROR does not fulfill `Send`
assert_send::<&'a [int]>(); //~ ERROR does not fulfill `Send`
- // ~ pointers are ok
- assert_send::<~int>();
+ // boxes are ok
+ assert_send::<Box<int>>();
assert_send::<~str>();
assert_send::<Vec<int> >();
// but not if they own a bad thing
- assert_send::<~&'a int>(); //~ ERROR does not fulfill `Send`
+ assert_send::<Box<&'a int>>(); //~ ERROR does not fulfill `Send`
// careful with object types, who knows what they close over...
assert_send::<&'static Dummy>(); //~ ERROR does not fulfill `Send`
assert_send::<&'a Dummy>(); //~ ERROR does not fulfill `Send`
assert_send::<&'a Dummy:Send>(); //~ ERROR does not fulfill `Send`
- assert_send::<~Dummy:>(); //~ ERROR does not fulfill `Send`
+ assert_send::<Box<Dummy:>>(); //~ ERROR does not fulfill `Send`
// ...unless they are properly bounded
assert_send::<&'static Dummy:Send>();
- assert_send::<~Dummy:Send>();
+ assert_send::<Box<Dummy:Send>>();
// but closure and object types can have lifetime bounds which make
// them not ok (FIXME #5121)
// assert_send::<proc:'a()>(); // ERROR does not fulfill `Send`
- // assert_send::<~Dummy:'a>(); // ERROR does not fulfill `Send`
+ // assert_send::<Box<Dummy:'a>>(); // ERROR does not fulfill `Send`
// unsafe ptrs are ok unless they point at unsendable things
assert_send::<*int>();
fn g(_: &mut int) {}
fn main() {
- f(~1); //~ ERROR unnecessary allocation, use & instead
- g(~1); //~ ERROR unnecessary allocation, use &mut instead
+ f(box 1); //~ ERROR unnecessary allocation, use & instead
+ g(box 1); //~ ERROR unnecessary allocation, use &mut instead
}
static USED_STATIC: int = 0;
static STATIC_USED_IN_ENUM_DISCRIMINANT: uint = 10;
-pub type typ = ~UsedStruct4;
+pub type typ = *UsedStruct4;
pub struct PubStruct();
struct PrivStruct; //~ ERROR: code is never used
struct UsedStruct1 { x: int }
}
pub enum pub_enum { foo1, bar1 }
-pub enum pub_enum2 { a(~StructUsedInEnum) }
+pub enum pub_enum2 { a(*StructUsedInEnum) }
pub enum pub_enum3 { Foo = STATIC_USED_IN_ENUM_DISCRIMINANT }
enum priv_enum { foo2, bar2 } //~ ERROR: code is never used
enum used_enum { foo3, bar3 }
#![allow(dead_code)]
#![allow(deprecated_owned_vector)]
+
struct Foo {
x: @int //~ ERROR type uses managed
}
-struct Bar { x: ~int } //~ ERROR type uses owned
+struct Bar { x: Box<int> } //~ ERROR type uses owned
fn main() {
- let _x : Bar = Bar {x : ~10}; //~ ERROR type uses owned
+ let _x : Bar = Bar {x : box 10}; //~ ERROR type uses owned
@2; //~ ERROR type uses managed
- ~2; //~ ERROR type uses owned
- fn g(_: ~Clone) {} //~ ERROR type uses owned
+ box 2; //~ ERROR type uses owned
+ fn g(_: Box<Clone>) {} //~ ERROR type uses owned
"".to_owned(); //~ ERROR type uses owned
proc() {}; //~ ERROR type uses owned
}
#![forbid(owned_heap_memory)]
+
struct Foo {
- x: ~int //~ ERROR type uses owned
+ x: Box<int> //~ ERROR type uses owned
}
fn main() {
- let _x : Foo = Foo {x : ~10};
+ let _x : Foo = Foo {x : box 10};
//~^ ERROR type uses owned
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn take(_x: ~int) {}
+
+fn take(_x: Box<int>) {}
fn main() {
- let x: ~int = ~25;
+ let x: Box<int> = box 25;
loop {
take(x); //~ ERROR use of moved value: `x`
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
fn main() {
- let y: ~int = ~42;
- let mut x: ~int;
+ let y: Box<int> = box 42;
+ let mut x: Box<int>;
loop {
println!("{:?}", y);
loop {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn main() {
- let y: ~int = ~42;
- let mut x: ~int;
+fn main() {
+ let y: Box<int> = box 42;
+ let mut x: Box<int>;
loop {
println!("{:?}", y); //~ ERROR use of moved value: `y`
while true { while true { while true { x = y; x.clone(); } } }
// except according to those terms.
fn main() {
- let x = ~5;
+ let x = box 5;
let y = x;
println!("{:?}", *x); //~ ERROR use of moved value: `x`
y.clone();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
fn send<T:Send>(ch: _chan<T>, data: T) {
println!("{:?}", ch);
println!("{:?}", data);
// Tests that "log(debug, message);" is flagged as using
// message after the send deinitializes it
-fn test00_start(ch: _chan<~int>, message: ~int, _count: ~int) {
+fn test00_start(ch: _chan<Box<int>>, message: Box<int>, _count: Box<int>) {
send(ch, message);
println!("{:?}", message); //~ ERROR use of moved value: `message`
}
// Test that trait types printed in error msgs include the type arguments.
fn main() {
- let x: ~HashMap<~str, ~str> = ~HashMap::new();
- let x: ~Map<~str, ~str> = x;
- let y: ~Map<uint, ~str> = ~x;
+ let x: Box<HashMap<~str, ~str>> = box HashMap::new();
+ let x: Box<Map<~str, ~str>> = x;
+ let y: Box<Map<uint, ~str>> = box x;
//~^ ERROR failed to find an implementation of trait std::container::Map<uint,~str>
// for ~std::container::Map<~str,~str>:Send
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct S {
- x: ~E
+ x: Box<E>
}
enum E {
- Foo(~S),
- Bar(~int),
+ Foo(Box<S>),
+ Bar(Box<int>),
Baz
}
}
fn main() {
- let s = S { x: ~Bar(~42) };
+ let s = S { x: box Bar(box 42) };
loop {
f(&s, |hellothere| {
match hellothere.x { //~ ERROR cannot move out
- ~Foo(_) => {}
- ~Bar(x) => println!("{}", x.to_str()), //~ NOTE attempting to move value to here
- ~Baz => {}
+ box Foo(_) => {}
+ box Bar(x) => println!("{}", x.to_str()), //~ NOTE attempting to move value to here
+ box Baz => {}
}
})
}
// temporary kinds wound up being stored in a cache and used later.
// See middle::ty::type_contents() for more information.
-struct List { key: int, next: Option<~List> }
-fn foo(node: ~List) -> int {
+struct List { key: int, next: Option<Box<List>> }
+
+fn foo(node: Box<List>) -> int {
let r = match node.next {
Some(right) => consume(right),
None => 0
consume(node) + r //~ ERROR use of partially moved value: `node`
}
-fn consume(v: ~List) -> int {
+fn consume(v: Box<List>) -> int {
v.key
}
use std::uint;
-fn test(_x: ~uint) {}
+fn test(_x: Box<uint>) {}
fn main() {
- let i = ~3;
+ let i = box 3;
let _f = || test(i); //~ ERROR cannot move out
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn dup(x: ~int) -> ~(~int,~int) { ~(x, x) } //~ ERROR use of moved value
+
+fn dup(x: Box<int>) -> Box<(Box<int>,Box<int>)> { box() (x, x) } //~ ERROR use of moved value
fn main() {
- dup(~3);
+ dup(box 3);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
type Noncopyable = proc();
struct Foo {
copied: int,
- moved: ~int,
+ moved: Box<int>,
noncopyable: Noncopyable
}
fn test0(f: Foo, g: Noncopyable, h: Noncopyable) {
// just copy implicitly copyable fields from `f`, no moves:
- let _b = Foo {moved: ~1, noncopyable: g, ..f};
- let _c = Foo {moved: ~2, noncopyable: h, ..f};
+ let _b = Foo {moved: box 1, noncopyable: g, ..f};
+ let _c = Foo {moved: box 2, noncopyable: h, ..f};
}
fn test1(f: Foo, g: Noncopyable, h: Noncopyable) {
fn test2(f: Foo, g: Noncopyable) {
// move non-copyable field
- let _b = Foo {copied: 22, moved: ~23, ..f};
+ let _b = Foo {copied: 22, moved: box 23, ..f};
let _c = Foo {noncopyable: g, ..f}; //~ ERROR use of partially moved value: `f`
}
// Tests that the new `box` syntax works with unique pointers and GC pointers.
use std::gc::Gc;
-use std::owned::HEAP;
+use std::owned::{Box, HEAP};
pub fn main() {
let x: Gc<int> = box(HEAP) 2; //~ ERROR mismatched types
let y: Gc<int> = box(HEAP)(1 + 2); //~ ERROR mismatched types
- let z: ~int = box(GC)(4 + 5); //~ ERROR mismatched types
+ let z: Box<int> = box(GC)(4 + 5); //~ ERROR mismatched types
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// Test that an object type `~Foo` is not considered to implement the
+// Test that an object type `Box<Foo>` is not considered to implement the
// trait `Foo`. Issue #5087.
+
trait Foo {}
fn take_foo<F:Foo>(f: F) {}
-fn take_object(f: ~Foo) { take_foo(f); } //~ ERROR failed to find an implementation of trait
+fn take_object(f: Box<Foo>) { take_foo(f); } //~ ERROR failed to find an implementation of trait
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait Foo {
fn borrowed(&self);
fn borrowed_mut(&mut self);
x.owned(); //~ ERROR does not implement any method
}
-fn owned_receiver(x: ~Foo) {
+fn owned_receiver(x: Box<Foo>) {
x.borrowed();
x.borrowed_mut(); // See [1]
x.managed(); //~ ERROR does not implement any method
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait A<T> {}
struct B<'a, T>(&'a A<T>);
trait X {}
impl<'a, T> X for B<'a, T> {}
-fn f<'a, T, U>(v: ~A<T>) -> ~X: {
- ~B(v) as ~X: //~ ERROR value may contain references; add `'static` bound to `T`
+fn f<'a, T, U>(v: Box<A<T>>) -> Box<X:> {
+ box B(v) as Box<X:> //~ ERROR value may contain references; add `'static` bound to `T`
}
-fn g<'a, T, U>(v: ~A<U>) -> ~X: {
- ~B(v) as ~X: //~ ERROR value may contain references; add `'static` bound to `U`
+fn g<'a, T, U>(v: Box<A<U>>) -> Box<X:> {
+ box B(v) as Box<X:> //~ ERROR value may contain references; add `'static` bound to `U`
}
-fn h<'a, T: 'static>(v: ~A<T>) -> ~X: {
- ~B(v) as ~X: // ok
+fn h<'a, T: 'static>(v: Box<A<T>>) -> Box<X:> {
+ box B(v) as Box<X:> // ok
}
fn main() {}
let i = @Cell::new(0);
{
// Can't do this copy
- let x = ~~~A {y: r(i)};
+ let x = box box box A {y: r(i)};
let _z = x.clone(); //~ ERROR failed to find an implementation
println!("{:?}", x);
}
#![allow(dead_code)]
#![allow(unused_imports)]
+
// public type, private value
pub mod foo1 {
pub trait Bar {
fn test_glob2() {
use foo2::*;
- let _x: ~Bar; //~ ERROR use of undeclared type name `Bar`
+ let _x: Box<Bar>; //~ ERROR use of undeclared type name `Bar`
}
// neither public
use foo3::*;
Bar(); //~ ERROR unresolved name `Bar`.
- let _x: ~Bar; //~ ERROR use of undeclared type name `Bar`
+ let _x: Box<Bar>; //~ ERROR use of undeclared type name `Bar`
}
fn main() {
#![allow(dead_code)]
#![allow(unused_imports)]
+
// public type, private value
pub mod foo1 {
pub trait Bar {
fn test_single2() {
use foo2::Bar; //~ ERROR `Bar` is private
- let _x : ~Bar;
+ let _x : Box<Bar>;
}
fn test_list2() {
use foo2::{Bar,Baz}; //~ ERROR `Bar` is private
- let _x: ~Bar;
+ let _x: Box<Bar>;
}
// neither public
use foo3::Bar; //~ ERROR `Bar` is private
Bar();
- let _x: ~Bar;
+ let _x: Box<Bar>;
}
fn test_list3() {
use foo3::{Bar,Baz}; //~ ERROR `Bar` is private
Bar();
- let _x: ~Bar;
+ let _x: Box<Bar>;
}
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait Foo { }
-fn foo<'a>(x: ~Foo:'a) { //~ ERROR only the 'static lifetime is accepted here
+fn foo<'a>(x: Box<Foo:'a>) { //~ ERROR only the 'static lifetime is accepted here
}
fn bar<'a, T:'a>() { //~ ERROR only the 'static lifetime is accepted here
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn arg_item(~ref x: ~int) -> &'static int {
+
+fn arg_item(box ref x: Box<int>) -> &'static int {
x //~^ ERROR borrowed value does not live long enough
}
-fn with<R>(f: |~int| -> R) -> R { f(~3) }
+fn with<R>(f: |Box<int>| -> R) -> R { f(box 3) }
fn arg_closure() -> &'static int {
- with(|~ref x| x) //~ ERROR borrowed value does not live long enough
+ with(|box ref x| x) //~ ERROR borrowed value does not live long enough
}
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct ctxt { v: uint }
trait get_ctxt {
}
-fn get_v(gc: ~get_ctxt) -> uint {
+fn get_v(gc: Box<get_ctxt>) -> uint {
gc.get_ctxt().v
}
fn main() {
let ctxt = ctxt { v: 22u };
let hc = has_ctxt { c: &ctxt };
- assert_eq!(get_v(~hc as ~get_ctxt), 22u);
+ assert_eq!(get_v(box hc as Box<get_ctxt>), 22u);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-type closure = ~lt/fn(); //~ ERROR expected `;` but found `/`
+type closure = Box<lt/fn()>; //~ ERROR expected `,` but found `/`
// except according to those terms.
fn f() {
- let a_box = ~mut 42;
+ let a_box = box mut 42;
//~^ ERROR found `mut` in ident position
//~^^ ERROR expected `;` but found `42`
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-type mut_box = ~mut int;
+type mut_box = Box<mut int>;
//~^ ERROR found `mut` in ident position
- //~^^ ERROR expected `;` but found `int`
+ //~^^ ERROR expected `,` but found `int`
+++ /dev/null
-// Copyright 2013-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.
-
-struct S;
-
-impl S {
- fn f(~mut self) {} //~ ERROR found `self` in ident position
- //~^ ERROR expected `:` but found `)`
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait add {
fn plus(&self, x: Self) -> Self;
}
-fn do_add(x: ~add, y: ~add) -> ~add {
+fn do_add(x: Box<add>, y: Box<add>) -> Box<add> {
x.plus(y) //~ ERROR cannot call a method whose type contains a self-type through an object
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-static mut a: ~int = ~3; //~ ERROR: mutable static items are not allowed to have owned pointers
+
+static mut a: Box<int> = box 3;
+//~^ ERROR mutable static items are not allowed to have owned pointers
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct BuildData {
foo: int,
- bar: ~int
+ bar: Box<int>,
}
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait Foo {
}
-fn a(_x: ~Foo:Send) {
+fn a(_x: Box<Foo:Send>) {
}
-fn c(x: ~Foo:Share+Send) {
+fn c(x: Box<Foo:Share+Send>) {
a(x);
}
-fn d(x: ~Foo:) {
+fn d(x: Box<Foo:>) {
a(x); //~ ERROR found no bounds
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct Foo;
-fn foo(_x: ~Foo:Send) { } //~ ERROR kind bounds can only be used on trait types
+fn foo(_x: Box<Foo:Send>) { } //~ ERROR kind bounds can only be used on trait types
fn main() { }
// Tests for "default" bounds inferred for traits with no bounds list.
+
trait Foo {}
-fn a(_x: ~Foo:Send) {
+fn a(_x: Box<Foo:Send>) {
}
fn b(_x: &'static Foo) { // should be same as &'static Foo:'static
}
-fn c(x: ~Foo:Share) {
+fn c(x: Box<Foo:Share>) {
a(x); //~ ERROR expected bounds `Send`
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct Struct {
person: &'static str
}
}
fn main() {
- let s: ~Trait<int> = ~Struct { person: "Fred" };
+ let s: Box<Trait<int>> = box Struct { person: "Fred" };
//~^ ERROR expected Trait<int>, but found Trait<&'static str>
//~^^ ERROR expected Trait<int>, but found Trait<&'static str>
s.f(1);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct Struct {
person: &'static str
}
fn main() {
let person = "Fred".to_owned();
let person: &str = person; //~ ERROR `person[..]` does not live long enough
- let s: ~Trait<&'static str> = ~Struct { person: person };
+ let s: Box<Trait<&'static str>> = box Struct { person: person };
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
impl bar for int { fn dup(&self) -> int { *self } fn blah<X>(&self) {} }
impl bar for uint { fn dup(&self) -> uint { *self } fn blah<X>(&self) {} }
fn main() {
10i.dup::<int>(); //~ ERROR does not take type parameters
10i.blah::<int, int>(); //~ ERROR incorrect number of type parameters
- (~10 as ~bar).dup(); //~ ERROR contains a self-type
+ (box 10 as Box<bar>).dup(); //~ ERROR contains a self-type
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait Foo {
fn f(&self);
}
}
fn main() {
- let x = ~Bar { x: 10 };
- let y: ~Foo = x as ~Foo;
+ let x = box Bar { x: 10 };
+ let y: Box<Foo> = x as Box<Foo>;
let _z = y.clone(); //~ ERROR does not implement any method in scope
}
}
fn main() {
- let i = ~r { b: true };
+ let i = box r { b: true };
let _j = i.clone(); //~ ERROR failed to find an implementation
println!("{:?}", i);
}
}
fn main() {
- let i = ~@100;
+ let i = box @100;
f(i); //~ ERROR does not fulfill `Send`
}
fn main() {
let i1 = @Cell::new(0);
let i2 = @Cell::new(1);
- let r1 = vec!(~r { i: i1 });
- let r2 = vec!(~r { i: i2 });
+ let r1 = vec!(box r { i: i1 });
+ let r2 = vec!(box r { i: i2 });
f(r1.clone(), r2.clone());
//~^ ERROR failed to find an implementation of
println!("{:?}", (r2, i1.get()));
// error-pattern:unreachable pattern
-enum foo { a(~foo, int), b(uint), }
-fn main() { match b(1u) { b(_) | a(~_, 1) => { } a(_, 1) => { } } }
+enum foo { a(Box<foo>, int), b(uint), }
+
+fn main() { match b(1u) { b(_) | a(box _, 1) => { } a(_, 1) => { } } }
// Test sized-ness checking in substitution.
+
// Unbounded.
fn f1<type X>(x: &X) {
f2::<X>(x); //~ ERROR instantiating a type parameter with an incompatible type `X`, which does n
}
// Test some tuples.
-fn f9<type X>(x1: ~S<X>, x2: ~E<X>) {
+fn f9<type X>(x1: Box<S<X>>, x2: Box<E<X>>) {
f5(&(*x1, 34)); //~ERROR instantiating a type parameter with an incompatible type `(S<X>,int)`,
f5(&(32, *x2)); //~ERROR instantiating a type parameter with an incompatible type `(int,E<X>)`,
}
// Test `type` local variables.
+
trait T for type {}
fn f1<type X>(x: &X) {
let y: (int, (X, int)); //~ERROR variable `y` has dynamically sized type `(int,(X,int))`
}
-fn f3<type X>(x1: ~X, x2: ~X, x3: ~X) {
+fn f3<type X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
let y: X = *x1; //~ERROR variable `y` has dynamically sized type `X`
let y = *x2; //~ERROR variable `y` has dynamically sized type `X`
let (y, z) = (*x3, 4); //~ERROR variable `y` has dynamically sized type `X`
}
-fn f4<type X: T>(x1: ~X, x2: ~X, x3: ~X) {
+fn f4<type X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
let y: X = *x1; //~ERROR variable `y` has dynamically sized type `X`
let y = *x2; //~ERROR variable `y` has dynamically sized type `X`
let (y, z) = (*x3, 4); //~ERROR variable `y` has dynamically sized type `X`
}
struct List {
- list: Vec<~ToStr> }
+ list: Vec<Box<ToStr>> }
impl List {
- fn push(&mut self, n: ~ToStr) {
+ fn push(&mut self, n: Box<ToStr>) {
self.list.push(n);
}
}
fn main() {
- let n = ~Number { n: 42 };
- let mut l = ~List { list: Vec::new() };
+ let n = box Number { n: 42 };
+ let mut l = box List { list: Vec::new() };
l.push(n);
let x = n.to_str();
//~^ ERROR: use of moved value: `n`
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct S {
- x: ~int
+ x: Box<int>,
}
impl S {
}
fn main() {
- let x = S { x: ~1 };
+ let x = S { x: box 1 };
println!("{}", x.foo());
}
let managed_val_interior_ref_1: &int = &managed_val.x;
let managed_val_interior_ref_2: &f64 = &managed_val.y;
- let unique_val = ~SomeStruct { x: 13, y: 26.5 };
+ let unique_val = box SomeStruct { x: 13, y: 26.5 };
let unique_val_ref: &SomeStruct = unique_val;
let unique_val_interior_ref_1: &int = &unique_val.x;
let unique_val_interior_ref_2: &f64 = &unique_val.y;
#![allow(unused_variable)]
+
fn main() {
let stack_val: (i16, f32) = (-14, -19f32);
let stack_val_ref: &(i16, f32) = &stack_val;
let managed_val: @(i16, f32) = @(-16, -21f32);
let managed_val_ref: &(i16, f32) = managed_val;
- let unique_val: ~(i16, f32) = ~(-17, -22f32);
+ let unique_val: Box<(i16, f32)> = box() (-17, -22f32);
let unique_val_ref: &(i16, f32) = unique_val;
zzz();
fn main() {
- let bool_box: ~bool = ~true;
+ let bool_box: Box<bool> = box true;
let bool_ref: &bool = bool_box;
- let int_box: ~int = ~-1;
+ let int_box: Box<int> = box -1;
let int_ref: &int = int_box;
- let char_box: ~char = ~'a';
+ let char_box: Box<char> = box 'a';
let char_ref: &char = char_box;
- let i8_box: ~i8 = ~68;
+ let i8_box: Box<i8> = box 68;
let i8_ref: &i8 = i8_box;
- let i16_box: ~i16 = ~-16;
+ let i16_box: Box<i16> = box -16;
let i16_ref: &i16 = i16_box;
- let i32_box: ~i32 = ~-32;
+ let i32_box: Box<i32> = box -32;
let i32_ref: &i32 = i32_box;
- let i64_box: ~i64 = ~-64;
+ let i64_box: Box<i64> = box -64;
let i64_ref: &i64 = i64_box;
- let uint_box: ~uint = ~1;
+ let uint_box: Box<uint> = box 1;
let uint_ref: &uint = uint_box;
- let u8_box: ~u8 = ~100;
+ let u8_box: Box<u8> = box 100;
let u8_ref: &u8 = u8_box;
- let u16_box: ~u16 = ~16;
+ let u16_box: Box<u16> = box 16;
let u16_ref: &u16 = u16_box;
- let u32_box: ~u32 = ~32;
+ let u32_box: Box<u32> = box 32;
let u32_ref: &u32 = u32_box;
- let u64_box: ~u64 = ~64;
+ let u64_box: Box<u64> = box 64;
let u64_ref: &u64 = u64_box;
- let f32_box: ~f32 = ~2.5;
+ let f32_box: Box<f32> = box 2.5;
let f32_ref: &f32 = f32_box;
- let f64_box: ~f64 = ~3.5;
+ let f64_box: Box<f64> = box 3.5;
let f64_ref: &f64 = f64_box;
zzz();
}
#![allow(unused_variable)]
fn main() {
- let a = ~1;
- let b = ~(2, 3.5);
+ let a = box 1;
+ let b = box() (2, 3.5);
let c = @4;
let d = @false;
_zzz();
#![feature(managed_boxes)]
#![allow(unused_variable)]
+
struct StructWithSomePadding {
x: i16,
y: i32,
fn main() {
- let unique = ~StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 };
+ let unique = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 };
let managed = @StructWithSomePadding { x: 88, y: 888, z: 8888, w: 88888 };
- let unique_dtor = ~StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 };
+ let unique_dtor = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 };
let managed_dtor = @StructWithDestructor { x: 33, y: 333, z: 3333, w: 33333 };
zzz();
fn main() {
some_generic_fun(0.5, 10);
- some_generic_fun(&29, ~110);
+ some_generic_fun(&29, box 110);
}
fn zzz() {()}
#![allow(unused_variable)]
+
struct Struct {
a: i64,
b: i32
zzz();
}
-fn unique_pointer(~dd: ~(int, int, int)) {
+fn unique_pointer(box dd: Box<(int, int, int)>) {
zzz();
}
managed_box(&(34, 35));
borrowed_pointer(&(36, 37));
contained_borrowed_pointer((&38, 39));
- unique_pointer(~(40, 41, 42));
+ unique_pointer(box() (40, 41, 42));
ref_binding((43, 44, 45));
ref_binding_in_tuple((46, (47, 48)));
ref_binding_in_struct(Struct { a: 49, b: 50 });
let (&cc, _) = (&38, 39);
// unique pointer
- let ~dd = ~(40, 41, 42);
+ let box dd = box() (40, 41, 42);
// ref binding
let ref ee = (43, 44, 45);
let _ = stack.self_by_ref(-1, -2_i8);
let _ = stack.self_by_val(-3, -4_i16);
- let owned = ~Struct { x: 1234.5 };
+ let owned = box Struct { x: 1234.5 };
let _ = owned.self_by_ref(-5, -6_i32);
let _ = owned.self_by_val(-7, -8_i64);
let _ = owned.self_owned(-9, -10.5_f32);
}
fn main() {
- let ordinary_unique = ~(-1, -2);
+ let ordinary_unique = box() (-1, -2);
- let managed_within_unique = ~ContainsManaged { x: -3, y: @-4 };
+ let managed_within_unique = box ContainsManaged { x: -3, y: @-4 };
zzz();
}
let _ = stack.self_by_ref(-1, -2);
let _ = stack.self_by_val(-3, -4);
- let owned = ~Variant1{ x: 1799, y: 1799 };
+ let owned = box Variant1{ x: 1799, y: 1799 };
let _ = owned.self_by_ref(-5, -6);
let _ = owned.self_by_val(-7, -8);
let _ = owned.self_owned(-9, -10);
let _ = stack.self_by_ref(-1, -2);
let _ = stack.self_by_val(-3, -4);
- let owned = ~Struct { x: 1234.5 };
+ let owned = box Struct { x: 1234.5 };
let _ = owned.self_by_ref(-5, -6);
let _ = owned.self_by_val(-7, -8);
let _ = owned.self_owned(-9, -10);
let _ = stack.self_by_ref(-1, -2);
let _ = stack.self_by_val(-3, -4);
- let owned = ~Struct { x: 200 };
+ let owned = box Struct { x: 200 };
let _ = owned.self_by_ref(-5, -6);
let _ = owned.self_by_val(-7, -8);
let _ = owned.self_owned(-9, -10);
let _ = stack.self_by_ref(-1, -2);
let _ = stack.self_by_val(-3, -4);
- let owned = ~Struct { x: 200 };
+ let owned = box Struct { x: 200 };
let _ = owned.self_by_ref(-5, -6);
let _ = owned.self_by_val(-7, -8);
let _ = owned.self_owned(-9, -10);
let _ = stack.self_by_ref(-1, -2);
let _ = stack.self_by_val(-3, -4);
- let owned = ~TupleStruct(200, -200.5);
+ let owned = box TupleStruct(200, -200.5);
let _ = owned.self_by_ref(-5, -6);
let _ = owned.self_by_val(-7, -8);
let _ = owned.self_owned(-9, -10);
#![allow(unused_variable)]
#![feature(struct_variant)]
+
enum Opt<T> {
Empty,
Val { val: T }
}
struct UniqueNode<T> {
- next: Opt<~UniqueNode<T>>,
+ next: Opt<Box<UniqueNode<T>>>,
value: T
}
}
struct LongCycle1<T> {
- next: ~LongCycle2<T>,
+ next: Box<LongCycle2<T>>,
value: T,
}
struct LongCycle2<T> {
- next: ~LongCycle3<T>,
+ next: Box<LongCycle3<T>>,
value: T,
}
struct LongCycle3<T> {
- next: ~LongCycle4<T>,
+ next: Box<LongCycle4<T>>,
value: T,
}
struct LongCycle4<T> {
- next: Option<~LongCycle1<T>>,
+ next: Option<Box<LongCycle1<T>>>,
value: T,
}
struct LongCycleWithAnonymousTypes {
- next: Opt<~~~~~LongCycleWithAnonymousTypes>,
+ next: Opt<Box<Box<Box<Box<Box<LongCycleWithAnonymousTypes>>>>>>,
value: uint,
}
fn main() {
let stack_unique: UniqueNode<u16> = UniqueNode {
next: Val {
- val: ~UniqueNode {
+ val: box UniqueNode {
next: Empty,
value: 1_u16,
}
value: 0_u16,
};
- let unique_unique: ~UniqueNode<u32> = ~UniqueNode {
+ let unique_unique: Box<UniqueNode<u32>> = box UniqueNode {
next: Val {
- val: ~UniqueNode {
+ val: box UniqueNode {
next: Empty,
value: 3,
}
let box_unique: @UniqueNode<u64> = @UniqueNode {
next: Val {
- val: ~UniqueNode {
+ val: box UniqueNode {
next: Empty,
value: 5,
}
let vec_unique: [UniqueNode<f32>, ..1] = [UniqueNode {
next: Val {
- val: ~UniqueNode {
+ val: box UniqueNode {
next: Empty,
value: 7.5,
}
let borrowed_unique: &UniqueNode<f64> = &UniqueNode {
next: Val {
- val: ~UniqueNode {
+ val: box UniqueNode {
next: Empty,
value: 9.5,
}
value: 10,
};
- let unique_managed: ~ManagedNode<u32> = ~ManagedNode {
+ let unique_managed: Box<ManagedNode<u32>> = box ManagedNode {
next: Val {
val: @ManagedNode {
next: Empty,
// LONG CYCLE
let long_cycle1: LongCycle1<u16> = LongCycle1 {
- next: ~LongCycle2 {
- next: ~LongCycle3 {
- next: ~LongCycle4 {
+ next: box LongCycle2 {
+ next: box LongCycle3 {
+ next: box LongCycle4 {
next: None,
value: 23,
},
};
let long_cycle2: LongCycle2<u32> = LongCycle2 {
- next: ~LongCycle3 {
- next: ~LongCycle4 {
+ next: box LongCycle3 {
+ next: box LongCycle4 {
next: None,
value: 26,
},
};
let long_cycle3: LongCycle3<u64> = LongCycle3 {
- next: ~LongCycle4 {
+ next: box LongCycle4 {
next: None,
value: 28,
},
};
// It's important that LongCycleWithAnonymousTypes is encountered only at the end of the
- // `~` chain.
- let long_cycle_w_anonymous_types = ~~~~~LongCycleWithAnonymousTypes {
+ // `box` chain.
+ let long_cycle_w_anonymous_types = box box box box box LongCycleWithAnonymousTypes {
next: Val {
- val: ~~~~~LongCycleWithAnonymousTypes {
+ val: box box box box box LongCycleWithAnonymousTypes {
next: Empty,
value: 31,
}
let _ = stack.self_by_ref(-1, -2);
let _ = stack.self_by_val(-3, -4);
- let owned = ~Struct { x: 200 };
+ let owned = box Struct { x: 200 };
let _ = owned.self_by_ref(-5, -6);
let _ = owned.self_by_val(-7, -8);
let _ = owned.self_owned(-9, -10);
let _ = stack.self_by_ref(-1, -2_i8);
let _ = stack.self_by_val(-3, -4_i16);
- let owned = ~Struct { x: 879 };
+ let owned = box Struct { x: 879 };
let _ = owned.self_by_ref(-5, -6_i32);
let _ = owned.self_by_val(-7, -8_i64);
let _ = owned.self_owned(-9, -10.5_f32);
#![allow(unused_variable)]
+
trait Trait {
fn method(&self) -> int { 0 }
}
fn main() {
let stack_struct = Struct { a:0, b: 1.0 };
let reference: &Trait = &stack_struct as &Trait;
- let unique: ~Trait = ~Struct { a:2, b: 3.0 } as ~Trait;
+ let unique: Box<Trait> = box Struct { a:2, b: 3.0 } as Box<Trait>;
}
// 0b01111100011111000111110001111100 = 2088533116
// 0b0111110001111100 = 31868
// 0b01111100 = 124
- let the_a = ~TheA { x: 0, y: 8970181431921507452 };
+ let the_a = box TheA { x: 0, y: 8970181431921507452 };
// 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
// 0b00010001000100010001000100010001 = 286331153
// 0b0001000100010001 = 4369
// 0b00010001 = 17
- let the_b = ~TheB (0, 286331153, 286331153);
+ let the_b = box TheB (0, 286331153, 286331153);
- let univariant = ~TheOnlyCase(123234);
+ let univariant = box TheOnlyCase(123234);
zzz();
}
};
let struct_ref = &a_struct;
- let owned = ~6;
+ let owned = box 6;
let managed = @7;
let closure = || {
c: 4
};
- let owned = ~5;
+ let owned = box 5;
let closure: proc() = proc() {
zzz();
};
let struct_ref = &a_struct;
- let owned = ~6;
+ let owned = box 6;
let managed = @7;
let closure = || {
// pp-exact
+
trait Tr { }
impl Tr for int { }
-fn foo(x: ~Tr: Share) -> ~Tr: Share { x }
+fn foo(x: Box<Tr: Share>) -> Box<Tr: Share> { x }
fn main() {
- let x: ~Tr: Share;
+ let x: Box<Tr: Share>;
- ~1 as ~Tr: Share;
+ box() 1 as Box<Tr: Share>;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:failed at '~Any'
+// error-pattern:failed at 'Box<Any>'
fn main() {
- fail!(~612_i64);
+ fail!(box 612_i64);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:failed at '~Any'
+// error-pattern:failed at 'Box<Any>'
+
fn main() {
- fail!(~413 as ~::std::any::Any:Send);
+ fail!(box 413 as Box<::std::any::Any:Send>);
}
// error-pattern:explicit failure
// Issue #2272 - unwind this without leaking the unique pointer
-struct X { y: Y, a: ~int }
+
+struct X { y: Y, a: Box<int> }
struct Y { z: @int }
y: Y {
z: @0
},
- a: ~0
+ a: box 0
};
fail!();
}
// except according to those terms.
// error-pattern: fail
-fn main() { ~fail!(); }
+fn main() { box fail!(); }
}
fn main() {
- let y = ~0;
+ let y = box 0;
let x: @proc():Send = @(proc() {
println!("{:?}", y.clone());
});
impl Drop for r {
fn drop(&mut self) {
unsafe {
- let _v2: ~int = cast::transmute(self.v);
+ let _v2: Box<int> = cast::transmute(self.v);
}
}
}
fn main() {
unsafe {
- let i1 = ~0;
+ let i1 = box 0;
let i1p = cast::transmute_copy(&i1);
cast::forget(i1);
let x = @r(i1p);
#![feature(managed_boxes)]
+
fn failfn() {
fail!();
}
fn main() {
- let x = @~~0;
+ let x = @box box 0;
failfn();
println!("{:?}", x);
}
}
fn main() {
- let x = @~0;
+ let x = @box 0;
failfn();
println!("{:?}", x);
}
}
fn partial() {
- let _x = ~f();
+ let _x = box f();
}
fn main() {
// error-pattern:fail
+
fn failfn() {
fail!();
}
fn main() {
- ~0;
+ box 0;
failfn();
}
--- /dev/null
+-include ../tools.mk
+
+# Testing various mixings of rlibs and dylibs. Makes sure that it's possible to
+# link an rlib to a dylib. The dependency tree among the file looks like:
+#
+# foo
+# / \
+# bar1 bar2
+# / \ /
+# baz baz2
+#
+# This is generally testing the permutations of the foo/bar1/bar2 layer against
+# the baz/baz2 layer
+
+all:
+ # Building just baz
+ $(RUSTC) --crate-type=rlib foo.rs
+ $(RUSTC) --crate-type=dylib bar1.rs
+ $(RUSTC) --crate-type=dylib,rlib baz.rs
+ $(RUSTC) --crate-type=bin baz.rs
+ rm $(TMPDIR)/*
+ $(RUSTC) --crate-type=dylib foo.rs
+ $(RUSTC) --crate-type=rlib bar1.rs
+ $(RUSTC) --crate-type=dylib,rlib baz.rs
+ $(RUSTC) --crate-type=bin baz.rs
+ rm $(TMPDIR)/*
+ # Building baz2
+ $(RUSTC) --crate-type=rlib foo.rs
+ $(RUSTC) --crate-type=dylib bar1.rs
+ $(RUSTC) --crate-type=dylib bar2.rs
+ $(RUSTC) --crate-type=dylib baz2.rs && exit 1 || exit 0
+ $(RUSTC) --crate-type=bin baz2.rs && exit 1 || exit 0
+ rm $(TMPDIR)/*
+ $(RUSTC) --crate-type=rlib foo.rs
+ $(RUSTC) --crate-type=rlib bar1.rs
+ $(RUSTC) --crate-type=dylib bar2.rs
+ $(RUSTC) --crate-type=dylib,rlib baz2.rs
+ $(RUSTC) --crate-type=bin baz2.rs
+ rm $(TMPDIR)/*
+ $(RUSTC) --crate-type=rlib foo.rs
+ $(RUSTC) --crate-type=dylib bar1.rs
+ $(RUSTC) --crate-type=rlib bar2.rs
+ $(RUSTC) --crate-type=dylib,rlib baz2.rs
+ $(RUSTC) --crate-type=bin baz2.rs
+ rm $(TMPDIR)/*
+ $(RUSTC) --crate-type=rlib foo.rs
+ $(RUSTC) --crate-type=rlib bar1.rs
+ $(RUSTC) --crate-type=rlib bar2.rs
+ $(RUSTC) --crate-type=dylib,rlib baz2.rs
+ $(RUSTC) --crate-type=bin baz2.rs
+ rm $(TMPDIR)/*
+ $(RUSTC) --crate-type=dylib foo.rs
+ $(RUSTC) --crate-type=rlib bar1.rs
+ $(RUSTC) --crate-type=rlib bar2.rs
+ $(RUSTC) --crate-type=dylib,rlib baz2.rs
+ $(RUSTC) --crate-type=bin baz2.rs
+ rm $(TMPDIR)/*
+ $(RUSTC) --crate-type=dylib foo.rs
+ $(RUSTC) --crate-type=dylib bar1.rs
+ $(RUSTC) --crate-type=rlib bar2.rs
+ $(RUSTC) --crate-type=dylib,rlib baz2.rs
+ $(RUSTC) --crate-type=bin baz2.rs
+ rm $(TMPDIR)/*
+ $(RUSTC) --crate-type=dylib foo.rs
+ $(RUSTC) --crate-type=rlib bar1.rs
+ $(RUSTC) --crate-type=dylib bar2.rs
+ $(RUSTC) --crate-type=dylib,rlib baz2.rs
+ $(RUSTC) --crate-type=bin baz2.rs
+ rm $(TMPDIR)/*
+ $(RUSTC) --crate-type=dylib foo.rs
+ $(RUSTC) --crate-type=dylib bar1.rs
+ $(RUSTC) --crate-type=dylib bar2.rs
+ $(RUSTC) --crate-type=dylib,rlib baz2.rs
+ $(RUSTC) --crate-type=bin baz2.rs
--- /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.
+
+extern crate foo;
--- /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.
+
+extern crate foo;
--- /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.
+
+extern crate bar1;
+
+fn main() {}
--- /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.
+
+extern crate bar1;
+extern crate bar2;
+
+fn main() {}
+
--- /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.
all:
$(RUSTC) rlib.rs
- $(RUSTC) dylib.rs && exit 1 || exit 0
+ $(RUSTC) dylib.rs
$(RUSTC) rlib.rs --crate-type=dylib
$(RUSTC) dylib.rs
rm $(call DYLIB,rlib-*)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct pair<A,B> {
a: A, b: B
}
}
}
-fn f<A:Clone + 'static>(a: A, b: u16) -> ~Invokable<A>: {
- ~Invoker {
+fn f<A:Clone + 'static>(a: A, b: u16) -> Box<Invokable<A>:> {
+ box Invoker {
a: a,
b: b,
- } as ~Invokable<A>:
+ } as Box<Invokable<A>>:
}
pub fn main() {
pub fn main() {
assert_eq!(14,14);
assert_eq!("abc".to_owned(),"abc".to_owned());
- assert_eq!(~Point{x:34},~Point{x:34});
+ assert_eq!(box Point{x:34},box Point{x:34});
assert_eq!(&Point{x:34},&Point{x:34});
assert_eq!(@Point{x:34},@Point{x:34});
}
}
pub fn main() {
- // NB: Associativity of ~, etc. in this context is surprising. These must be parenthesized
-
([1]).test_imm();
(vec!(1)).as_slice().test_imm();
(&[1]).test_imm();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait double {
fn double(~self) -> uint;
}
}
pub fn main() {
- let x = ~(~3u as ~double);
+ let x = box() (box 3u as Box<double>);
assert_eq!(x.double(), 6u);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait double {
fn double(~self) -> uint;
}
-impl double for ~uint {
+impl double for Box<uint> {
fn double(~self) -> uint { **self * 2u }
}
pub fn main() {
- let x = ~~~~~3u;
+ let x = box box box box box 3u;
assert_eq!(x.double(), 6u);
}
}
pub fn main() {
- let x = ~~3u;
+ let x = box box 3u;
assert_eq!(x.double(), 6u);
}
}
pub fn main() {
- let x = ~3u;
+ let x = box 3u;
assert_eq!(x.double(), 6u);
}
use collections::Bitv;
fn bitv_test() {
- let mut v1 = ~Bitv::new(31, false);
- let v2 = ~Bitv::new(31, true);
+ let mut v1 = box Bitv::new(31, false);
+ let v2 = box Bitv::new(31, true);
v1.union(v2);
}
#![feature(managed_boxes)]
+
fn borrow(x: &int, f: |x: &int|) {
f(x)
}
-fn test1(x: @~int) {
+fn test1(x: @Box<int>) {
borrow(&*(*x).clone(), |p| {
let x_a = &**x as *int;
assert!((x_a as uint) != (p as *int as uint));
}
pub fn main() {
- test1(@~22);
+ test1(@box 22);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
fn borrow(_v: &int) {}
-fn borrow_from_arg_imm_ref(v: ~int) {
+fn borrow_from_arg_imm_ref(v: Box<int>) {
borrow(v);
}
-fn borrow_from_arg_mut_ref(v: &mut ~int) {
+fn borrow_from_arg_mut_ref(v: &mut Box<int>) {
borrow(*v);
}
-fn borrow_from_arg_copy(v: ~int) {
+fn borrow_from_arg_copy(v: Box<int>) {
borrow(v);
}
#![feature(macro_rules)]
+
struct Foo {
a: int
}
pub enum Bar {
- Bar1, Bar2(int, ~Bar),
+ Bar1, Bar2(int, Box<Bar>),
}
impl Foo {
- fn elaborate_stm(&mut self, s: ~Bar) -> ~Bar {
+ fn elaborate_stm(&mut self, s: Box<Bar>) -> Box<Bar> {
macro_rules! declare(
($id:expr, $rest:expr) => ({
self.check_id($id);
- ~Bar2($id, $rest)
+ box Bar2($id, $rest)
})
);
match s {
- ~Bar2(id, rest) => declare!(id, self.elaborate_stm(rest)),
+ box Bar2(id, rest) => declare!(id, self.elaborate_stm(rest)),
_ => fail!()
}
}
// except according to those terms.
pub fn main() {
- let bar = ~3;
+ let bar = box 3;
let h: proc() -> int = proc() *bar;
assert_eq!(h(), 3);
}
use std::mem::swap;
-struct Ints {sum: ~int, values: Vec<int> }
+struct Ints {sum: Box<int>, values: Vec<int> }
fn add_int(x: &mut Ints, v: int) {
*x.sum += v;
}
pub fn main() {
- let mut ints = ~Ints {sum: ~0, values: Vec::new()};
+ let mut ints = box Ints {sum: box 0, values: Vec::new()};
add_int(ints, 22);
add_int(ints, 44);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct Rec {
- f: ~int,
+ f: Box<int>,
}
struct Outer {
}
struct Innermost {
- h: ~int,
+ h: Box<int>,
}
fn borrow(_v: &int) {}
-fn box_mut(v: &mut ~int) {
+fn box_mut(v: &mut Box<int>) {
borrow(*v); // OK: &mut -> &imm
}
borrow(v.f.g.h); // OK: &mut -> &imm
}
-fn box_imm(v: &~int) {
+fn box_imm(v: &Box<int>) {
borrow(*v); // OK
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn foo(x: &mut ~u8) {
- *x = ~5;
+
+fn foo(x: &mut Box<u8>) {
+ *x = box 5;
}
pub fn main() {
- foo(&mut ~4);
+ foo(&mut box 4);
}
extern crate log;
extern crate native;
+use log::{set_logger, Logger, LogRecord};
use std::fmt;
use std::io::{ChanReader, ChanWriter};
-use log::{set_logger, Logger, LogRecord};
struct MyWriter(ChanWriter);
let (tx, rx) = channel();
let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
spawn(proc() {
- set_logger(~MyWriter(w) as ~Logger:Send);
+ set_logger(box MyWriter(w) as Box<Logger:Send>);
debug!("debug");
info!("info");
});
// aux-build:cci_class_cast.rs
extern crate cci_class_cast;
+
use std::to_str::ToStr;
use cci_class_cast::kitty::cat;
-fn print_out(thing: ~ToStr, expected: ~str) {
+fn print_out(thing: Box<ToStr>, expected: ~str) {
let actual = thing.to_str();
println!("{}", actual);
assert_eq!(actual, expected);
}
pub fn main() {
- let nyan: ~ToStr = ~cat(0u, 2, "nyan".to_owned()) as ~ToStr;
+ let nyan: Box<ToStr> = box cat(0u, 2, "nyan".to_owned()) as Box<ToStr>;
print_out(nyan, "nyan".to_owned());
}
}
}
-fn print_out(thing: ~ToStr, expected: ~str) {
+fn print_out(thing: Box<ToStr>, expected: ~str) {
let actual = thing.to_str();
println!("{}", actual);
assert_eq!(actual, expected);
}
pub fn main() {
- let nyan: ~ToStr = ~cat(0u, 2, "nyan".to_owned()) as ~ToStr;
+ let nyan: Box<ToStr> = box cat(0u, 2, "nyan".to_owned()) as Box<ToStr>;
print_out(nyan, "nyan".to_owned());
}
struct Test { x: int }
impl Test {
- fn get_x(&self) -> Option<~int> {
- Some(~self.x)
+ fn get_x(&self) -> Option<Box<int>> {
+ Some(box self.x)
}
}
// This test verifies that temporaries created for `while`'s and `if`
// conditions are dropped after the condition is evaluated.
+
struct Temporary;
static mut DROPPED: int = 0;
fn do_stuff(&self) -> bool {true}
}
-fn borrow() -> ~Temporary { ~Temporary }
+fn borrow() -> Box<Temporary> { box Temporary }
pub fn main() {
end_of_block!(AddFlags { bits: ref _x }, AddFlags(1));
end_of_block!(&AddFlags { bits }, &AddFlags(1));
end_of_block!((_, ref _y), (AddFlags(1), 22));
- end_of_block!(~ref _x, ~AddFlags(1));
- end_of_block!(~_x, ~AddFlags(1));
+ end_of_block!(box ref _x, box AddFlags(1));
+ end_of_block!(box _x, box AddFlags(1));
end_of_block!(_, { { check_flags(0); &AddFlags(1) } });
end_of_block!(_, &((Box { f: AddFlags(1) }).f));
end_of_block!(_, &(([AddFlags(1)])[0]));
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// Test cleanup of rvalue temporary that occurs while `~` construction
+// Test cleanup of rvalue temporary that occurs while `box` construction
// is in progress. This scenario revealed a rather terrible bug. The
// ingredients are:
//
-// 1. Partial cleanup of `~` is in scope,
+// 1. Partial cleanup of `box` is in scope,
// 2. cleanup of return value from `get_bar()` is in scope,
// 3. do_it() fails.
//
// This led to a bug because `the top-most frame that was to be
-// cleaned (which happens to be the partial cleanup of `~`) required
+// cleaned (which happens to be the partial cleanup of `box`) required
// multiple basic blocks, which led to us dropping part of the cleanup
// from the top-most frame.
//
Bickwick(Foo)
}
-struct Foo { field: ~uint }
+struct Foo { field: Box<uint> }
fn do_it(x: &[uint]) -> Foo {
fail!()
pub fn fails() {
let x = 2;
let mut y = Vec::new();
- y.push(~Bickwick(do_it(get_bar(x).as_slice())));
+ y.push(box Bickwick(do_it(get_bar(x).as_slice())));
}
pub fn main() {
}
pub fn main() {
- let z = ~Pair { a : 10, b : 12};
+ let z = box Pair { a : 10, b : 12};
let f: proc():Send = proc() {
assert_eq!(z.a, 10);
// storing closure data (as we used to do), the u64 would
// overwrite the u16.
+
struct Pair<A,B> {
a: A, b: B
}
}
}
-fn f<A:Clone + 'static>(a: A, b: u16) -> ~Invokable<A>: {
- ~Invoker {
+fn f<A:Clone + 'static>(a: A, b: u16) -> Box<Invokable<A>:> {
+ box Invoker {
a: a,
b: b,
- } as ~Invokable<A>:
+ } as Box<Invokable<A>>:
}
pub fn main() {
foo(F{field: 42});
foo((1, 2u));
foo(@1);*/
- foo(~1);
+ foo(box 1);
}
// except according to those terms.
pub fn main() {
- assert!(Some(~()).is_some());
+ assert!(Some(box() ()).is_some());
struct Foo;
- assert!(Some(~Foo).is_some());
+ assert!(Some(box Foo).is_some());
let xs: ~[()] = ~[];
assert!(Some(xs).is_some());
// except according to those terms.
pub fn main() {
- let x = *~();
+ let x = *box() ();
}
// except according to those terms.
use std::result::{Result,Ok};
-static C: Result<(), ~int> = Ok(());
+
+static C: Result<(), Box<int>> = Ok(());
// This is because of yet another bad assertion (ICE) about the null side of a nullable enum.
// So we won't actually compile if the bug is present, but we check the value in main anyway.
}
pub fn main() {
- let mut m = ~linear_map::<(),()>();
+ let mut m = box linear_map::<(),()>();
assert_eq!(m.len(), 0);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait Foo {
fn f(~self);
}
}
pub fn main() {
- let x = ~S { x: 3 };
- let y = x as ~Foo;
+ let x = box S { x: 3 };
+ let y = x as Box<Foo>;
y.f();
}
impl Nus for thing { fn f(&self) {} }
pub fn main() {
- let y = ~thing(A {a: 10});
+ let y = box thing(A {a: 10});
assert_eq!(y.clone().bar(), 10);
assert_eq!(y.quux(), 10);
// except according to those terms.
+type compare<'a, T> = |Box<T>, Box<T>|: 'a -> bool;
-type compare<'a, T> = |~T, ~T|: 'a -> bool;
-
-fn test_generic<T:Clone>(expected: ~T, eq: compare<T>) {
- let actual: ~T = { expected.clone() };
+fn test_generic<T:Clone>(expected: Box<T>, eq: compare<T>) {
+ let actual: Box<T> = { expected.clone() };
assert!((eq(expected, actual)));
}
fn test_box() {
- fn compare_box(b1: ~bool, b2: ~bool) -> bool {
+ fn compare_box(b1: Box<bool>, b2: Box<bool>) -> bool {
println!("{}", *b1);
println!("{}", *b2);
return *b1 == *b2;
}
- test_generic::<bool>(~true, compare_box);
+ test_generic::<bool>(box true, compare_box);
}
pub fn main() { test_box(); }
}
fn test_vec() {
- fn compare_vec(v1: ~int, v2: ~int) -> bool { return v1 == v2; }
- test_generic::<~int>(~1, compare_vec);
+ fn compare_vec(v1: Box<int>, v2: Box<int>) -> bool { return v1 == v2; }
+ test_generic::<Box<int>>(box 1, compare_vec);
}
pub fn main() { test_vec(); }
-pub fn main() { let x = { ~100 }; assert!((*x == 100)); }
+pub fn main() { let x = { box 100 }; assert!((*x == 100)); }
// Tests for if as expressions returning boxed types
fn test_box() {
- let rs = if true { ~100 } else { ~101 };
+ let rs = if true { box 100 } else { box 101 };
assert_eq!(*rs, 100);
}
// except according to those terms.
+type compare<T> = |Box<T>, Box<T>|: 'static -> bool;
-type compare<T> = |~T, ~T|: 'static -> bool;
-
-fn test_generic<T:Clone>(expected: ~T, eq: compare<T>) {
- let actual: ~T = match true {
+fn test_generic<T:Clone>(expected: Box<T>, eq: compare<T>) {
+ let actual: Box<T> = match true {
true => { expected.clone() },
_ => fail!("wat")
};
}
fn test_box() {
- fn compare_box(b1: ~bool, b2: ~bool) -> bool { return *b1 == *b2; }
- test_generic::<bool>(~true, compare_box);
+ fn compare_box(b1: Box<bool>, b2: Box<bool>) -> bool {
+ return *b1 == *b2;
+ }
+ test_generic::<bool>(box true, compare_box);
}
pub fn main() { test_box(); }
}
fn test_vec() {
- fn compare_box(v1: ~int, v2: ~int) -> bool { return v1 == v2; }
- test_generic::<~int>(~1, compare_box);
+ fn compare_box(v1: Box<int>, v2: Box<int>) -> bool { return v1 == v2; }
+ test_generic::<Box<int>>(box 1, compare_box);
}
pub fn main() { test_vec(); }
// except according to those terms.
-
-
-
// Tests for match as expressions resulting in boxed types
fn test_box() {
- let res = match true { true => { ~100 }, _ => fail!() };
+ let res = match true { true => { box 100 }, _ => fail!() };
assert_eq!(*res, 100);
}
fn new(x:int,y:int) -> NoFoo { NoFoo { copied: x, nocopy: ncint(y) } }
}
-struct MoveFoo { copied: int, moved: ~int, }
+struct MoveFoo { copied: int, moved: Box<int>, }
impl MoveFoo {
- fn new(x:int,y:int) -> MoveFoo { MoveFoo { copied: x, moved: ~y } }
+ fn new(x:int,y:int) -> MoveFoo { MoveFoo { copied: x, moved: box y } }
}
struct DropNoFoo { inner: NoFoo }
// Case 2: Owned
let f = DropMoveFoo::new(5, 6);
- let b = DropMoveFoo { inner: MoveFoo { moved: ~7, ..f.inner }};
- let c = DropMoveFoo { inner: MoveFoo { moved: ~8, ..f.inner }};
+ let b = DropMoveFoo { inner: MoveFoo { moved: box 7, ..f.inner }};
+ let c = DropMoveFoo { inner: MoveFoo { moved: box 8, ..f.inner }};
assert_eq!(f.inner.copied, 5);
assert_eq!(*f.inner.moved, 6);
// copying move-by-default fields from `f`, so it moves:
let f = MoveFoo::new(11, 12);
- let b = MoveFoo {moved: ~13, ..f};
+ let b = MoveFoo {moved: box 13, ..f};
let c = MoveFoo {copied: 14, ..f};
assert_eq!(b.copied, 11);
assert_eq!(*b.moved, 13);
// Test that we do not leak when the arg pattern must drop part of the
// argument (in this case, the `y` field).
+
struct Foo {
- x: ~uint,
- y: ~uint,
+ x: Box<uint>,
+ y: Box<uint>,
}
fn foo(Foo {x, ..}: Foo) -> *uint {
}
pub fn main() {
- let obj = ~1;
+ let obj = box 1;
let objptr: *uint = &*obj;
- let f = Foo {x: obj, y: ~2};
+ let f = Foo {x: obj, y: box 2};
let xptr = foo(f);
assert_eq!(objptr, xptr);
}
// exec-env:RUST_POISON_ON_FREE=1
-// Test argument patterns where we create refs to the inside of `~`
+// Test argument patterns where we create refs to the inside of
// boxes. Make sure that we don't free the box as we match the
// pattern.
-fn getaddr(~ref x: ~uint) -> *uint {
+
+fn getaddr(box ref x: Box<uint>) -> *uint {
let addr: *uint = &*x;
addr
}
-fn checkval(~ref x: ~uint) -> uint {
+fn checkval(box ref x: Box<uint>) -> uint {
*x
}
pub fn main() {
- let obj = ~1;
+ let obj = box 1;
let objptr: *uint = &*obj;
let xptr = getaddr(obj);
assert_eq!(objptr, xptr);
- let obj = ~22;
+ let obj = box 22;
assert_eq!(checkval(obj), 22);
}
// except according to those terms.
-
fn id<T:Send>(t: T) -> T { return t; }
pub fn main() {
- let expected = ~100;
- let actual = id::<~int>(expected.clone());
+ let expected = box 100;
+ let actual = id::<Box<int>>(expected.clone());
println!("{:?}", *actual);
assert_eq!(*expected, *actual);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-struct Recbox<T> {x: ~T}
-fn reclift<T>(t: T) -> Recbox<T> { return Recbox {x: ~t}; }
+struct Recbox<T> {x: Box<T>}
+
+fn reclift<T>(t: T) -> Recbox<T> { return Recbox {x: box t}; }
pub fn main() {
let foo: int = 17;
// except according to those terms.
-fn f<T>(x: ~T) -> ~T { return x; }
+fn f<T>(x: Box<T>) -> Box<T> { return x; }
-pub fn main() { let x = f(~3); println!("{:?}", *x); }
+pub fn main() { let x = f(box 3); println!("{:?}", *x); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait Foo<T> {
fn get(&self) -> T;
}
}
pub fn main() {
- let x = ~S { x: 1 };
- let y = x as ~Foo<int>;
+ let x = box S { x: 1 };
+ let y = x as Box<Foo<int>>;
assert_eq!(y.get(), 1);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct Triple<T> { x: T, y: T, z: T }
-fn box_it<T>(x: Triple<T>) -> ~Triple<T> { return ~x; }
+fn box_it<T>(x: Triple<T>) -> Box<Triple<T>> { return box x; }
pub fn main() {
- let x: ~Triple<int> = box_it::<int>(Triple{x: 1, y: 2, z: 3});
+ let x: Box<Triple<int>> = box_it::<int>(Triple{x: 1, y: 2, z: 3});
assert_eq!(x.y, 2);
}
t!(format!("{:?}", 1), "1");
t!(format!("{:?}", A), "A");
t!(format!("{:?}", ()), "()");
- t!(format!("{:?}", @(~1, "foo")), "@(~1, \"foo\")");
+ t!(format!("{:?}", @(box 1, "foo")), "@(box 1, \"foo\")");
// Various edge cases without formats
t!(format!(""), "");
test_order();
// make sure that format! doesn't move out of local variables
- let a = ~3;
+ let a = box 3;
format!("{:?}", a);
format!("{:?}", a);
fn test_unique() {
let i = @Cell::new(0);
{
- let _a = ~r(i);
+ let _a = box r(i);
}
assert_eq!(i.get(), 1);
}
pub fn main() {
unsafe {
- let mut x = ~1;
+ let mut x = box 1;
assert_eq!(rusti::atomic_load(&*x), 1);
*x = 5;
pub fn main() {
unsafe {
- let x = ~1;
+ let x = box 1;
let mut y = rusti::init();
let mut z: *uint = transmute(&x);
rusti::move_val_init(&mut y, x);
// Regression test for issue #10682
// Nested `proc` usage can't use outer owned data
-fn work(_: ~int) {}
+
+fn work(_: Box<int>) {}
fn foo(_: proc()) {}
pub fn main() {
- let a = ~1;
+ let a = box 1;
foo(proc() { foo(proc() { work(a) }) })
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
pub fn main() {
fn f() {
};
- let _: ~fn() = ~f;
+ let _: Box<fn()> = box f;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct DroppableStruct;
static mut DROPPED: bool = false;
}
trait MyTrait { }
-impl MyTrait for ~DroppableStruct {}
+impl MyTrait for Box<DroppableStruct> {}
-struct Whatever { w: ~MyTrait }
+struct Whatever { w: Box<MyTrait> }
impl Whatever {
- fn new(w: ~MyTrait) -> Whatever {
+ fn new(w: Box<MyTrait>) -> Whatever {
Whatever { w: w }
}
}
fn main() {
{
- let f = ~DroppableStruct;
- let _a = Whatever::new(~f as ~MyTrait);
+ let f = box DroppableStruct;
+ let _a = Whatever::new(box f as Box<MyTrait>);
}
assert!(unsafe { DROPPED });
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
#[deriving(Clone)]
enum Noun
{
Atom(int),
- Cell(~Noun, ~Noun)
+ Cell(Box<Noun>, Box<Noun>)
}
fn fas(n: &Noun) -> Noun
{
- match n
- {
- &Cell(~Atom(2), ~Cell(ref a, _)) => (**a).clone(),
+ match n {
+ &Cell(box Atom(2), box Cell(ref a, _)) => (**a).clone(),
_ => fail!("Invalid fas pattern")
}
}
pub fn main() {
- fas(&Cell(~Atom(2), ~Cell(~Atom(2), ~Atom(3))));
+ fas(&Cell(box Atom(2), box Cell(box Atom(2), box Atom(3))));
}
--- /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.
+
+// aux-build:issue-12133-rlib.rs
+// aux-build:issue-12133-dylib.rs
+
+extern crate a = "issue-12133-rlib";
+extern crate b = "issue-12133-dylib";
+
+fn main() {}
--- /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.
+
+// aux-build:issue-12133-rlib.rs
+// aux-build:issue-12133-dylib.rs
+// no-prefer-dynamic
+
+extern crate a = "issue-12133-rlib";
+extern crate b = "issue-12133-dylib";
+
+fn main() {}
--- /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.
+
+// aux-build:issue-12133-rlib.rs
+// aux-build:issue-12133-dylib.rs
+// aux-build:issue-12133-dylib2.rs
+
+extern crate other = "issue-12133-dylib2";
+
+fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait clam<A> {
fn chowder(&self, y: A);
}
}
}
-fn f<A>(x: ~clam<A>, a: A) {
+fn f<A>(x: Box<clam<A>>, a: A) {
x.chowder(a);
}
pub fn main() {
let c = foo(42);
- let d: ~clam<int> = ~c as ~clam<int>;
+ let d: Box<clam<int>> = box c as Box<clam<int>>;
f(d, c.x);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn a_val(x: ~int, y: ~int) -> int {
+
+fn a_val(x: Box<int>, y: Box<int>) -> int {
*x + *y
}
pub fn main() {
- let z = ~22;
+ let z = box 22;
a_val(z.clone(), z.clone());
}
pub fn packet<T:Send>() -> *packet<T> {
unsafe {
- let p: *packet<T> = cast::transmute(~Stuff{
+ let p: *packet<T> = cast::transmute(box Stuff{
state: empty,
blocked_task: None::<Task>,
payload: None::<T>
// We should consider moving this to ::std::unsafe, although I
// suspect graydon would want us to use void pointers instead.
- pub unsafe fn uniquify<T>(x: *T) -> ~T {
+ pub unsafe fn uniquify<T>(x: *T) -> Box<T> {
cast::transmute(x)
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait hax { }
impl<A> hax for A { }
-fn perform_hax<T: 'static>(x: ~T) -> ~hax: {
- ~x as ~hax:
+fn perform_hax<T: 'static>(x: Box<T>) -> Box<hax:> {
+ box x as Box<hax:>
}
fn deadcode() {
- perform_hax(~"deadcode".to_owned());
+ perform_hax(box "deadcode".to_owned());
}
pub fn main() {
- let _ = perform_hax(~42);
+ let _ = perform_hax(box 42);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait hax { }
impl<A> hax for A { }
-fn perform_hax<T: 'static>(x: ~T) -> ~hax: {
- ~x as ~hax:
+fn perform_hax<T: 'static>(x: Box<T>) -> Box<hax:> {
+ box x as Box<hax:>
}
fn deadcode() {
- perform_hax(~"deadcode".to_owned());
+ perform_hax(box "deadcode".to_owned());
}
pub fn main() {
- perform_hax(~42);
+ perform_hax(box 42);
}
int_value(i64),
}
-fn lookup(table: ~json::Object, key: ~str, default: ~str) -> ~str
+fn lookup(table: Box<json::Object>, key: ~str, default: ~str) -> ~str
{
match table.find(&key) {
option::Some(&json::String(ref s)) => {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
//type t = { a: int };
// type t = { a: bool };
type t = bool;
pub fn main() {
// let x = ({a: 4i} as it);
- // let y = ~({a: 4i});
- // let z = ~({a: 4i} as it);
- // let z = ~({a: true} as it);
- let z = ~(~true as ~it);
+ // let y = box ({a: 4i});
+ // let z = box ({a: 4i} as it);
+ // let z = box ({a: true} as it);
+ let z = box() (box true as Box<it>);
// x.f();
// y.f();
// (*z).f();
pub fn main() {
let mut buggy_map: HashMap<uint, &uint> = HashMap::new();
- let x = ~1;
+ let x = box 1;
buggy_map.insert(42, &*x);
}
// except according to those terms.
pub fn main() {
- let mut x = ~3;
+ let mut x = box 3;
x = x;
assert_eq!(*x, 3);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
pub fn main() {
trait Text {
fn to_str(&self) -> ~str;
}
- fn to_string(t: ~Text) {
+ fn to_string(t: Box<Text>) {
println!("{}", t.to_str());
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait T {
fn print(&self);
}
}
pub fn main() {
- let s: ~S = ~S { s: 5 };
+ let s: Box<S> = box S { s: 5 };
print_s(s);
- let t: ~T = s as ~T;
+ let t: Box<T> = s as Box<T>;
print_t(t);
}
#![allow(path_statement)]
pub fn main() {
- let y = ~1;
+ let y = box 1;
y;
}
impl Drop for NonCopyable {
fn drop(&mut self) {
let NonCopyable(p) = *self;
- let _v = unsafe { transmute::<*c_void, ~int>(p) };
+ let _v = unsafe { transmute::<*c_void, Box<int>>(p) };
}
}
pub fn main() {
- let t = ~0;
- let p = unsafe { transmute::<~int, *c_void>(t) };
+ let t = box 0;
+ let p = unsafe { transmute::<Box<int>, *c_void>(t) };
let _z = NonCopyable(p);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-struct T { a: ~int }
+
+struct T { a: Box<int> }
trait U {
fn f(self);
}
-impl U for ~int {
+impl U for Box<int> {
fn f(self) { }
}
pub fn main() {
- let T { a: a } = T { a: ~0 };
+ let T { a: a } = T { a: box 0 };
a.f();
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
pub struct Scheduler {
/// The event loop used to drive the scheduler and perform I/O
- event_loop: ~int
+ event_loop: Box<int>
}
pub fn main() { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
pub trait EventLoop {
}
}
pub struct Scheduler {
- event_loop: ~EventLoop,
+ event_loop: Box<EventLoop>,
}
impl Scheduler {
- pub fn new(event_loop: ~EventLoop) -> Scheduler {
+ pub fn new(event_loop: Box<EventLoop>) -> Scheduler {
Scheduler {
event_loop: event_loop,
}
}
pub fn main() {
- let _sched = Scheduler::new(~UvEventLoop::new() as ~EventLoop);
+ let _sched = Scheduler::new(box UvEventLoop::new() as Box<EventLoop>);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct Dog {
name : ~str
}
pub fn main() {
- let snoopy = ~Dog{name: "snoopy".to_owned()};
- let bubbles = ~Dog{name: "bubbles".to_owned()};
- let barker = [snoopy as ~Barks, bubbles as ~Barks];
+ let snoopy = box Dog{name: "snoopy".to_owned()};
+ let bubbles = box Dog{name: "bubbles".to_owned()};
+ let barker = [snoopy as Box<Barks>, bubbles as Box<Barks>];
for pup in barker.iter() {
println!("{}", pup.bark());
#![feature(managed_boxes)]
+
pub struct Foo {
a: int,
}
struct Bar<'a> {
- a: ~Option<int>,
+ a: Box<Option<int>>,
b: &'a Foo,
}
fn check(a: @Foo) {
- let _ic = Bar{ b: a, a: ~None };
+ let _ic = Bar{ b: a, a: box None };
}
pub fn main(){}
}
pub fn main() {
- let g : ~HashMap<int, int> = ~HashMap::new();
- let _g2 : ~Graph<int,int> = g as ~Graph<int,int>;
+ let g : Box<HashMap<int,int>> = box HashMap::new();
+ let _g2 : Box<Graph<int,int>> = g as Box<Graph<int,int>>;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
pub enum Thing {
- A(~Foo)
+ A(Box<Foo>)
}
pub trait Foo {}
impl Foo for Struct {}
pub fn main() {
- match A(~Struct as ~Foo) {
+ match A(box Struct as Box<Foo>) {
A(_a) => 0,
};
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn foo(~(_x, _y): ~(int, int)) {}
+
+fn foo(box (_x, _y): Box<(int, int)>) {}
pub fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait Foo {
- fn foo(~self) { bar(self as ~Foo); }
+ fn foo(~self) { bar(self as Box<Foo>); }
}
-fn bar(_b: ~Foo) { }
+fn bar(_b: Box<Foo>) { }
fn main() {}
*/
+
pub fn main() {}
trait A {}
impl<T: 'static> A for T {}
-fn owned1<T: 'static>(a: T) { ~a as ~A:; } /* note `:` */
-fn owned2<T: 'static>(a: ~T) { a as ~A:; }
-fn owned3<T: 'static>(a: ~T) { ~a as ~A:; }
+fn owned1<T: 'static>(a: T) { box a as Box<A:>; } /* note `:` */
+fn owned2<T: 'static>(a: Box<T>) { a as Box<A:>; }
+fn owned3<T: 'static>(a: Box<T>) { box a as Box<A:>; }
// except according to those terms.
pub fn main() {
- match &[(~5,~7)] {
+ match &[(box 5,box 7)] {
ps => {
let (ref y, _) = ps[0];
assert!(**y == 5);
}
}
- match Some(&[(~5,)]) {
+ match Some(&[(box 5,)]) {
Some(ps) => {
let (ref y,) = ps[0];
assert!(**y == 5);
None => ()
}
- match Some(&[(~5,~7)]) {
+ match Some(&[(box 5,box 7)]) {
Some(ps) => {
let (ref y, ref z) = ps[0];
assert!(**y == 5);
#![feature(macro_rules)]
+
pub trait bomb { fn boom(&self, Ident); }
pub struct S;
impl bomb for S { fn boom(&self, _: Ident) { } }
Ident {name: 0x6789ABCD }
}
-pub fn light_fuse(fld: ~bomb) {
+pub fn light_fuse(fld: Box<bomb>) {
int3!();
let f = || {
int3!();
}
pub fn main() {
- let b = ~S as ~bomb;
+ let b = box S as Box<bomb>;
light_fuse(b);
}
struct Thing1<'a> {
- baz: &'a [~int],
- bar: ~u64,
+ baz: &'a [Box<int>],
+ bar: Box<u64>,
}
struct Thing2<'a> {
- baz: &'a [~int],
+ baz: &'a [Box<int>],
bar: u64,
}
pub fn main() {
let _t1_fixed = Thing1 {
baz: &[],
- bar: ~32,
+ bar: box 32,
};
Thing1 {
baz: Vec::new().as_slice(),
- bar: ~32,
+ bar: box 32,
};
let _t2_fixed = Thing2 {
baz: &[],
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait repeat<A> { fn get(&self) -> A; }
-impl<A:Clone + 'static> repeat<A> for ~A {
+impl<A:Clone + 'static> repeat<A> for Box<A> {
fn get(&self) -> A {
(**self).clone()
}
}
-fn repeater<A:Clone + 'static>(v: ~A) -> ~repeat<A>: {
+fn repeater<A:Clone + 'static>(v: Box<A>) -> Box<repeat<A>:> {
// Note: owned kind is not necessary as A appears in the trait type
- ~v as ~repeat<A>: // No
+ box v as Box<repeat<A>:> // No
}
pub fn main() {
let x = 3;
- let y = repeater(~x);
+ let y = repeater(box x);
assert_eq!(x, y.get());
}
// Make sure #1399 stays fixed
-struct A { a: ~int }
+
+struct A { a: Box<int> }
fn foo() -> ||: 'static -> int {
- let k = ~22;
+ let k = box 22;
let _u = A {a: k.clone()};
let result: ||: 'static -> int = || 22;
result
// Make sure #1399 stays fixed
-struct A { a: ~int }
+
+struct A { a: Box<int> }
pub fn main() {
fn invoke(f: ||) { f(); }
- let k = ~22;
+ let k = box 22;
let _u = A {a: k.clone()};
invoke(|| println!("{:?}", k.clone()) )
}
// except according to those terms.
-
fn leaky<T>(_t: T) { }
-pub fn main() { let x = ~10; leaky::<~int>(x); }
+pub fn main() { let x = box 10; leaky::<Box<int>>(x); }
--- /dev/null
+// Copyright 2013-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-android
+// ignore-win32
+
+#![feature(phase)]
+
+#[phase(syntax, link)]
+extern crate log;
+
+use std::io::{Process, ProcessConfig};
+use std::os;
+use std::str;
+
+fn main() {
+ let args = os::args();
+ if args.len() > 1 && args[1].as_slice() == "child" {
+ debug!("foo");
+ debug!("bar");
+ return
+ }
+
+ let env = [("RUST_LOG".to_owned(), "debug".to_owned())];
+ let config = ProcessConfig {
+ program: args[0].as_slice(),
+ args: &["child".to_owned()],
+ env: Some(env.as_slice()),
+ ..ProcessConfig::new()
+ };
+ let p = Process::configure(config).unwrap().wait_with_output();
+ assert!(p.status.success());
+ let mut lines = str::from_utf8(p.error.as_slice()).unwrap().lines();
+ assert!(lines.next().unwrap().contains("foo"));
+ assert!(lines.next().unwrap().contains("bar"));
+}
+
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-struct Pair { a: ~int, b: ~int }
+
+struct Pair { a: Box<int>, b: Box<int> }
pub fn main() {
- let mut x = ~Pair {a: ~10, b: ~20};
+ let mut x = box Pair {a: box 10, b: box 20};
match x {
- ~Pair {a: ref mut a, b: ref mut _b} => {
- assert!(**a == 10); *a = ~30; assert!(**a == 30);
+ box Pair {a: ref mut a, b: ref mut _b} => {
+ assert!(**a == 10); *a = box 30; assert!(**a == 30);
}
}
}
// except according to those terms.
pub fn main() {
- match ~100 {
- ~x => {
+ match box 100 {
+ box x => {
println!("{:?}", x);
assert_eq!(x, 100);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn foo(x: Option<~int>, b: bool) -> int {
+
+fn foo(x: Option<Box<int>>, b: bool) -> int {
match x {
None => { 1 }
Some(ref x) if b => { *x.clone() }
}
pub fn main() {
- foo(Some(~22), true);
- foo(Some(~22), false);
+ foo(Some(box 22), true);
+ foo(Some(box 22), false);
foo(None, true);
foo(None, false);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
#[deriving(Clone)]
struct Triple {
x: int,
z: int,
}
-fn test(x: bool, foo: ~Triple) -> int {
+fn test(x: bool, foo: Box<Triple>) -> int {
let bar = foo;
- let mut y: ~Triple;
- if x { y = bar; } else { y = ~Triple{x: 4, y: 5, z: 6}; }
+ let mut y: Box<Triple>;
+ if x { y = bar; } else { y = box Triple{x: 4, y: 5, z: 6}; }
return y.y;
}
pub fn main() {
- let x = ~Triple{x: 1, y: 2, z: 3};
+ let x = box Triple{x: 1, y: 2, z: 3};
assert_eq!(test(true, x.clone()), 2);
assert_eq!(test(true, x.clone()), 2);
assert_eq!(test(true, x.clone()), 2);
struct X { x: int, y: int, z: int }
-pub fn main() { let x = ~X{x: 1, y: 2, z: 3}; let y = x; assert!((y.y == 2)); }
+pub fn main() {
+ let x = box X{x: 1, y: 2, z: 3};
+ let y = x;
+ assert!((y.y == 2));
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
#[deriving(Clone)]
struct Triple {
x: int,
z: int,
}
-fn test(x: bool, foo: ~Triple) -> int {
+fn test(x: bool, foo: Box<Triple>) -> int {
let bar = foo;
- let mut y: ~Triple;
- if x { y = bar; } else { y = ~Triple {x: 4, y: 5, z: 6}; }
+ let mut y: Box<Triple>;
+ if x { y = bar; } else { y = box Triple {x: 4, y: 5, z: 6}; }
return y.y;
}
pub fn main() {
- let x = ~Triple{x: 1, y: 2, z: 3};
+ let x = box Triple{x: 1, y: 2, z: 3};
for _ in range(0u, 10000u) {
assert_eq!(test(true, x.clone()), 2);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct Triple {a: int, b: int, c: int}
-fn test(foo: ~Triple) -> ~Triple {
+fn test(foo: Box<Triple>) -> Box<Triple> {
let foo = foo;
let bar = foo;
let baz = bar;
return quux;
}
-pub fn main() { let x = ~Triple{a: 1, b: 2, c: 3}; let y = test(x); assert!((y.c == 3)); }
+pub fn main() {
+ let x = box Triple{a: 1, b: 2, c: 3};
+ let y = test(x);
+ assert!((y.c == 3));
+}
// except according to those terms.
-fn test(foo: ~Vec<int> ) { assert!((*foo.get(0) == 10)); }
+fn test(foo: Box<Vec<int>> ) { assert!((*foo.get(0) == 10)); }
pub fn main() {
- let x = ~vec!(10);
+ let x = box vec!(10);
// Test forgetting a local by move-in
test(x);
// Test forgetting a temporary by move-in.
- test(~vec!(10));
+ test(box vec!(10));
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn f(mut y: ~int) {
+
+fn f(mut y: Box<int>) {
*y = 5;
assert_eq!(*y, 5);
}
fn g() {
- let frob: |~int| = |mut q| { *q = 2; assert!(*q == 2); };
- let w = ~37;
+ let frob: |Box<int>| = |mut q| { *q = 2; assert!(*q == 2); };
+ let w = box 37;
frob(w);
}
pub fn main() {
- let z = ~17;
+ let z = box 17;
f(z);
g();
}
// Tests that the new `box` syntax works with unique pointers and GC pointers.
use std::gc::Gc;
-use std::owned::HEAP;
+use std::owned::{Box, HEAP};
struct Structure {
x: int,
}
pub fn main() {
- let x: ~int = box(HEAP) 2;
- let y: ~int = box 2;
+ let x: Box<int> = box(HEAP) 2;
+ let y: Box<int> = box 2;
let z: Gc<int> = box(GC) 2;
let a: Gc<Structure> = box(GC) Structure {
x: 10,
y: 20,
};
- let b: ~int = box()(1 + 2);
+ let b: Box<int> = box()(1 + 2);
let c = box()(3 + 4);
let d = box(GC)(5 + 6);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::owned::Box;
fn f(x: Box<int>) {
let y: &int = x;
pub fn main() {
check_type!(&17: &int);
- check_type!(~18: ~int);
+ check_type!(box 18: Box<int>);
check_type!(@19: @int);
check_type!("foo".to_owned(): ~str);
check_type!(vec!(20, 22): Vec<int> );
pub fn main() {
check_type!(&'static int);
- check_type!(~int);
+ check_type!(Box<int>);
check_type!(@int);
check_type!(~str);
check_type!(extern fn());
// Test invoked `&self` methods on owned objects where the values
-// closed over contain managed values. This implies that the ~ boxes
+// closed over contain managed values. This implies that the boxes
// will have headers that must be skipped over.
trait FooTrait {
}
pub fn main() {
- let foos: Vec<~FooTrait:> = vec!(
- ~BarStruct{ x: @0 } as ~FooTrait:,
- ~BarStruct{ x: @1 } as ~FooTrait:,
- ~BarStruct{ x: @2 } as ~FooTrait:
+ let foos: Vec<Box<FooTrait:>> = vec!(
+ box BarStruct{ x: @0 } as Box<FooTrait:>,
+ box BarStruct{ x: @1 } as Box<FooTrait:>,
+ box BarStruct{ x: @2 } as Box<FooTrait:>
);
for i in range(0u, foos.len()) {
// except according to those terms.
// Test invoked `&self` methods on owned objects where the values
-// closed over do not contain managed values, and thus the ~ boxes do
+// closed over do not contain managed values, and thus the boxes do
// not have headers.
}
pub fn main() {
- let foos: Vec<~FooTrait> = vec!(
- ~BarStruct{ x: 0 } as ~FooTrait,
- ~BarStruct{ x: 1 } as ~FooTrait,
- ~BarStruct{ x: 2 } as ~FooTrait
+ let foos: Vec<Box<FooTrait>> = vec!(
+ box BarStruct{ x: 0 } as Box<FooTrait>,
+ box BarStruct{ x: 1 } as Box<FooTrait>,
+ box BarStruct{ x: 2 } as Box<FooTrait>
);
for i in range(0u, foos.len()) {
// except according to those terms.
// Test invoked `&self` methods on owned objects where the values
-// closed over contain managed values. This implies that the ~ boxes
+// closed over contain managed values. This implies that the boxes
// will have headers that must be skipped over.
+
trait FooTrait {
fn foo(~self) -> uint;
}
}
pub fn main() {
- let foo = ~BarStruct{ x: 22 } as ~FooTrait;
+ let foo = box BarStruct{ x: 22 } as Box<FooTrait:>;
assert_eq!(22, foo.foo());
}
pub fn main() {
assert_eq!(Rc::new(5u).to_uint(), Some(5));
- assert_eq!((~&~&Rc::new(~~&~5u)).to_uint(), Some(5));
+ assert_eq!((box &box &Rc::new(box box &box 5u)).to_uint(), Some(5));
let point = Rc::new(Point {x: 2, y: 4});
assert_eq!(point.x, 2);
assert_eq!(point.y, 4);
pub fn main() {
assert_eq!(*Rc::new(5), 5);
- assert_eq!(***Rc::new(~~5), 5);
+ assert_eq!(***Rc::new(box box 5), 5);
assert_eq!(*Rc::new(Point {x: 2, y: 4}), Point {x: 2, y: 4});
let i = Rc::new(RefCell::new(2));
fn f<T: 'static>(_x: T) {}
pub fn main() {
- f(~5);
+ f(box 5);
}
#![allow(dead_code)]
+
trait A<T> {}
trait B<T, U> {}
trait C<'a, U> {}
}
fn foo1<T>(_: &A<T>: Send) {}
-fn foo2<T>(_: ~A<T>: Send + Share) {}
-fn foo3<T>(_: ~B<int, uint>: 'static) {}
-fn foo4<'a, T>(_: ~C<'a, T>: 'static + Send) {}
-fn foo5<'a, T>(_: ~foo::D<'a, T>: 'static + Send) {}
+fn foo2<T>(_: Box<A<T>: Send + Share>) {}
+fn foo3<T>(_: Box<B<int, uint>: 'static>) {}
+fn foo4<'a, T>(_: Box<C<'a, T>: 'static + Send>) {}
+fn foo5<'a, T>(_: Box<foo::D<'a, T>: 'static + Send>) {}
pub fn main() {}
#![allow(dead_code)]
#![allow(unused_imports)]
+
// public type, private value
pub mod foo1 {
pub trait Bar {
fn test_single1() {
use foo1::Bar;
- let _x: ~Bar;
+ let _x: Box<Bar>;
}
fn test_list1() {
use foo1::{Bar,Baz};
- let _x: ~Bar;
+ let _x: Box<Bar>;
}
fn test_glob1() {
use foo1::*;
- let _x: ~Bar;
+ let _x: Box<Bar>;
}
// private type, public value
use foo3::Bar;
Bar();
- let _x: ~Bar;
+ let _x: Box<Bar>;
}
fn test_list3() {
use foo3::{Bar,Baz};
Bar();
- let _x: ~Bar;
+ let _x: Box<Bar>;
}
fn test_glob3() {
use foo3::*;
Bar();
- let _x: ~Bar;
+ let _x: Box<Bar>;
}
fn main() {
fn sums_to_using_uniq(v: Vec<int> , sum: int) -> bool {
let mut i = 0u;
- let mut sum0 = ~0;
+ let mut sum0 = box 0;
while i < v.len() {
*sum0 += *v.get(i);
i += 1u;
fn sums_to_using_uniq_rec(v: Vec<int> , sum: int) -> bool {
let mut i = 0u;
- let mut sum0 = F {f: ~0};
+ let mut sum0 = F {f: box 0};
while i < v.len() {
*sum0.f += *v.get(i);
i += 1u;
println!("y={}", y);
assert_eq!(y, 6);
- let x = ~6;
+ let x = box 6;
let y = x.get();
println!("y={}", y);
assert_eq!(y, 6);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct Point {
x: int,
y: int
}
struct Character {
- pos: ~Point
+ pos: Box<Point>,
}
fn get_x<'r>(x: &'r Character) -> &'r int {
}
pub fn main() {
- let p = ~3u;
+ let p = box 3u;
let r = foo(p);
assert_eq!(r, 3u);
}
#![feature(issue_5723_bootstrap)]
+
trait Foo { }
-fn foo<'a>(x: ~Foo:'a) {
+fn foo<'a>(x: Box<Foo:'a>) {
}
fn bar<'a, T:'a>() {
v2: [int, ..3],
v3: Vec<int> ,
v4: C,
- v5: ~C,
+ v5: Box<C>,
v6: Option<C>
}
fn get_v5_ref<'v>(a: &'v A, _i: uint) -> &'v int {
match &a.value {
- &B {v5: ~C {f: ref v}, ..} => v
+ &B {v5: box C {f: ref v}, ..} => v
}
}
v2: [23, 24, 25],
v3: vec!(26, 27, 28),
v4: C { f: 29 },
- v5: ~C { f: 30 },
+ v5: box C { f: 30 },
v6: Some(C { f: 31 })}};
let p = get_v1(&a);
// Tests that you can use an early-bound lifetime parameter as
// on of the generic parameters in a trait.
+
trait Trait<'a> {
fn long(&'a self) -> int;
fn short<'b>(&'b self) -> int;
}
}
-impl<'t> MakerTrait<'t> for ~Trait<'t> {
- fn mk() -> ~Trait<'t> { ~(4,5) as ~Trait }
+impl<'t> MakerTrait<'t> for Box<Trait<'t>> {
+ fn mk() -> Box<Trait<'t>> { box() (4,5) as Box<Trait> }
}
enum List<'l> {
assert_eq!(object_invoke2(&t), 3);
assert_eq!(field_invoke2(&s2), 3);
- let m : ~Trait = make_val();
+ let m : Box<Trait> = make_val();
assert_eq!(object_invoke1(m), (4,5));
assert_eq!(object_invoke2(m), 5);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct X {
a: int
}
self
}
- fn change_again(mut ~self) -> ~Self {
+ fn change_again(mut ~self) -> Box<Self> {
self.set_to(45);
self
}
let new_x = x.change();
assert_eq!(new_x.a, 55);
- let x = ~new_x;
+ let x = box new_x;
let new_x = x.change_again();
assert_eq!(new_x.a, 45);
}
use std::rc::Rc;
pub fn main() {
- let mut x = ~3;
+ let mut x = box 3;
x = x;
assert!(*x == 3);
}
fn test05() {
- let three = ~3;
+ let three = box 3;
let fn_to_send: proc(int):Send = proc(n) {
println!("{}", *three + n); // will copy x into the closure
assert_eq!(*three, 3);
// Possibly-dynamic size of typaram should be cleared at pointer boundary.
+
fn bar<T: Sized>() { }
-fn foo<T>() { bar::<~T>() }
+fn foo<T>() { bar::<Box<T>>() }
pub fn main() { }
pub fn main() {
let (tx, rx) = channel::<uint>();
- let x = ~1;
+ let x = box 1;
let x_in_parent = &(*x) as *int as uint;
task::spawn(proc() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait Foo {
}
-fn a(_x: ~Foo:) {
+fn a(_x: Box<Foo:>) {
}
-fn b(_x: ~Foo:Send) {
+fn b(_x: Box<Foo:Send>) {
}
-fn c(x: ~Foo:Share+Send) {
+fn c(x: Box<Foo:Share+Send>) {
a(x);
}
-fn d(x: ~Foo:Send) {
+fn d(x: Box<Foo:Send>) {
b(x);
}
-fn e(x: ~Foo) { // sugar for ~Foo:Owned
+fn e(x: Box<Foo>) { // sugar for Box<Foo:Owned>
a(x);
}
let dogge1 = Dogge { bark_decibels: 100, tricks_known: 42, name: "alan_turing".to_owned() };
let dogge2 = Dogge { bark_decibels: 55, tricks_known: 11, name: "albert_einstein".to_owned() };
let fishe = Goldfyshe { swim_speed: 998, name: "alec_guinness".to_owned() };
- let arc = Arc::new(vec!(~catte as ~Pet:Share+Send,
- ~dogge1 as ~Pet:Share+Send,
- ~fishe as ~Pet:Share+Send,
- ~dogge2 as ~Pet:Share+Send));
+ let arc = Arc::new(vec!(box catte as Box<Pet:Share+Send>,
+ box dogge1 as Box<Pet:Share+Send>,
+ box fishe as Box<Pet:Share+Send>,
+ box dogge2 as Box<Pet:Share+Send>));
let (tx1, rx1) = channel();
let arc1 = arc.clone();
task::spawn(proc() { check_legs(arc1); tx1.send(()); });
rx3.recv();
}
-fn check_legs(arc: Arc<Vec<~Pet:Share+Send>>) {
+fn check_legs(arc: Arc<Vec<Box<Pet:Share+Send>>>) {
let mut legs = 0;
for pet in arc.iter() {
legs += pet.num_legs();
}
assert!(legs == 12);
}
-fn check_names(arc: Arc<Vec<~Pet:Share+Send>>) {
+fn check_names(arc: Arc<Vec<Box<Pet:Share+Send>>>) {
for pet in arc.iter() {
pet.name(|name| {
assert!(name[0] == 'a' as u8 && name[1] == 'l' as u8);
})
}
}
-fn check_pedigree(arc: Arc<Vec<~Pet:Share+Send>>) {
+fn check_pedigree(arc: Arc<Vec<Box<Pet:Share+Send>>>) {
for pet in arc.iter() {
assert!(pet.of_good_pedigree());
}
struct TreeR {
left: Option<Tree>,
right: Option<Tree>,
- val: ~to_str:Send
+ val: Box<to_str:Send>
}
trait to_str {
pub fn main() {
let t1 = Tree(@RefCell::new(TreeR{left: None,
right: None,
- val: ~1 as ~to_str:Send}));
+ val: box 1 as Box<to_str:Send>}));
let t2 = Tree(@RefCell::new(TreeR{left: Some(t1),
right: Some(t1),
- val: ~2 as ~to_str:Send}));
+ val: box 2 as Box<to_str:Send>}));
let expected = "[2, some([1, none, none]), some([1, none, none])]".to_owned();
assert!(t2.to_str_() == expected);
assert!(foo(t2) == expected);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
trait Trait<T> {
fn f(&self, x: T);
}
pub fn main() {
let a = Struct { x: 1, y: 2 };
- let b: ~Trait<&'static str> = ~a;
+ let b: Box<Trait<&'static str>> = box a;
b.f("Mary");
let c: &Trait<&'static str> = &a;
c.f("Joe");
}
}
-fn foo(mut a: ~Writer) {
+fn foo(mut a: Box<Writer>) {
a.write(bytes!("Hello\n"));
}
pub fn main() {
let a = Struct { x: 1, y: 2 };
- let b: ~Trait = ~a;
+ let b: Box<Trait> = box a;
b.f();
let c: &Trait = &a;
c.f();
let out = io::stdout();
- foo(~out);
+ foo(box out);
}
}
-pub fn main () {
+pub fn main() {
// Some tests of random things
f(0);
assert_eq!(g(0i, 3.14, 1), (3.14, 1));
assert_eq!(g(false, 3.14, 1), (3.14, 1));
- let obj = ~0i as ~A;
+ let obj = box 0i as Box<A>;
assert_eq!(obj.h(), 11);
// test for #8664
+
pub trait Trait2<A> {
fn doit(&self);
}
* task <unnamed> failed at 'index out of bounds: the len is 1 but the index is 1',
* src/librustc/middle/subst.rs:58
*/
- t: ~Trait2<A2>
+ t: Box<Trait2<A2>>
}
impl<A1, A2, A3> Impl<A1, A2, A3> {
}
pub fn main() {
- let a = ~() as ~Trait<u8, u8>;
+ let a = box() () as Box<Trait<u8, u8>>;
assert_eq!(a.method(Constant), 0);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
#![feature(managed_boxes)]
+
fn p_foo<T>(_pinned: T) { }
fn s_foo<T>(_shared: T) { }
fn u_foo<T:Send>(_unique: T) { }
p_foo(r(10));
p_foo(@r(10));
- p_foo(~r(10));
+ p_foo(box r(10));
p_foo(@10);
- p_foo(~10);
+ p_foo(box 10);
p_foo(10);
s_foo(@r(10));
s_foo(@10);
- s_foo(~10);
+ s_foo(box 10);
s_foo(10);
- u_foo(~10);
+ u_foo(box 10);
u_foo(10);
}
struct Pointy {
a : maybe_pointy,
- c : ~int,
+ c : Box<int>,
d : proc():Send->(),
}
fn empty_pointy() -> @RefCell<Pointy> {
return @RefCell::new(Pointy {
a : none,
- c : ~22,
+ c : box 22,
d : proc() {},
})
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
struct X {
a: int
}
trait Changer {
- fn change(mut ~self) -> ~Self;
+ fn change(mut ~self) -> Box<Self>;
}
impl Changer for X {
- fn change(mut ~self) -> ~X {
+ fn change(mut ~self) -> Box<X> {
self.a = 55;
self
}
}
pub fn main() {
- let x = ~X { a: 32 };
+ let x = box X { a: 32 };
let new_x = x.change();
assert_eq!(new_x.a, 55);
}
// except according to those terms.
pub fn main() {
- let mut i = ~1;
+ let mut i = box 1;
// Should be a copy
let mut j;
j = i.clone();
#![allow(dead_assignment)]
pub fn main() {
- let i = ~1;
- let mut j = ~2;
+ let i = box 1;
+ let mut j = box 2;
// Should drop the previous value of j
j = i;
assert_eq!(*j, 1);
}
pub fn main() {
- let t = f(~100);
- assert_eq!(t, ~100);
- let t = f(~@vec!(100));
- assert_eq!(t, ~@vec!(100));
+ let t = f(box 100);
+ assert_eq!(t, box 100);
+ let t = f(box @vec!(100));
+ assert_eq!(t, box @vec!(100));
}
pub fn main() {
let mut i;
- i = ~1;
+ i = box 1;
assert_eq!(*i, 1);
}
struct J { j: int }
pub fn main() {
- let i = ~J {
+ let i = box J {
j: 100
};
assert_eq!(i.j, 100);
pub fn main() {
- let i = ~vec!(100);
+ let i = box vec!(100);
assert_eq!(*i.get(0), 100);
}
// except according to those terms.
pub fn main() {
- let i = ~100;
- assert!(i == ~100);
- assert!(i < ~101);
- assert!(i <= ~100);
- assert!(i > ~99);
- assert!(i >= ~99);
+ let i = box 100;
+ assert!(i == box 100);
+ assert!(i < box 101);
+ assert!(i <= box 100);
+ assert!(i > box 99);
+ assert!(i >= box 99);
}
pub fn main() {
enum t { t1(int), t2(int), }
- let _x = ~t1(10);
+ let _x = box t1(10);
/*alt *x {
t1(a) {
}*/
/*alt x {
- ~t1(a) {
+ box t1(a) {
assert_eq!(a, 10);
}
_ { fail!(); }
// except according to those terms.
pub fn main() {
- ~100;
+ box 100;
}
fn vec() {
// except according to those terms.
pub fn main() {
- let mut i = ~1;
+ let mut i = box 1;
// Should be a copy
let mut j = i.clone();
*i = 2;
// except according to those terms.
pub fn main() {
- let i = ~1;
+ let i = box 1;
let j = i;
assert_eq!(*j, 1);
}
// except according to those terms.
pub fn main() {
- let i = ~100;
+ let i = box 100;
assert_eq!(*i, 100);
}
// except according to those terms.
pub fn main() {
- let i = ~100;
+ let i = box 100;
let j = i;
assert_eq!(*j, 100);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
pub fn main() {
- let _: ~int;
+ let _: Box<int>;
}
-fn f(_i: ~int) -> ~int {
+fn f(_i: Box<int>) -> Box<int> {
fail!();
}
// except according to those terms.
pub fn main() {
- let i = ~100;
+ let i = box 100;
assert_eq!(*i, 100);
}
struct Foo { a: int, b: int }
pub fn main() {
- let ~Foo{a, b} = ~Foo{a: 100, b: 200};
+ let box Foo{a, b} = box Foo{a: 100, b: 200};
assert_eq!(a + b, 300);
}
// except according to those terms.
pub fn main() {
- let _x = ~vec!(0,0,0,0,0);
+ let _x = box vec!(0,0,0,0,0);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn f(i: ~int) {
+
+fn f(i: Box<int>) {
assert_eq!(*i, 100);
}
pub fn main() {
- let i = ~100;
+ let i = box 100;
f(i);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn f(i: &mut ~int) {
- *i = ~200;
+
+fn f(i: &mut Box<int>) {
+ *i = box 200;
}
pub fn main() {
- let mut i = ~100;
+ let mut i = box 100;
f(&mut i);
assert_eq!(*i, 200);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn f(i: ~int) {
+
+fn f(i: Box<int>) {
assert_eq!(*i, 100);
}
pub fn main() {
- f(~100);
- let i = ~100;
+ f(box 100);
+ let i = box 100;
f(i);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn f() -> ~int {
- ~100
+
+fn f() -> Box<int> {
+ box 100
}
pub fn main() {
- assert_eq!(f(), ~100);
+ assert_eq!(f(), box 100);
}
// Issue #976
-fn f<T>(x: ~T) {
+
+fn f<T>(x: Box<T>) {
let _x2 = x;
}
pub fn main() { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+
fn test1() {
- enum bar { u(~int), w(int), }
+ enum bar { u(Box<int>), w(int), }
- let x = u(~10);
+ let x = u(box 10);
assert!(match x {
u(a) => {
println!("{:?}", a);
pub fn main() {
- let mut a = vec!(~10);
+ let mut a = vec!(box 10);
let b = a.clone();
assert_eq!(**a.get(0), 10);
// except according to those terms.
pub fn main() {
- let vect = vec!(~100);
- assert!(*vect.get(0) == ~100);
+ let vect = vec!(box 100);
+ assert!(*vect.get(0) == box 100);
}
// except according to those terms.
pub fn main() {
- let _i = ~100;
+ let _i = box 100;
}
assert!(i != j);
}
- let i = ~100;
- let j = ~100;
+ let i = box 100;
+ let j = box 100;
f(i, j);
- let i = ~100;
- let j = ~101;
+ let i = box 100;
+ let j = box 101;
g(i, j);
}
assert!(i != j);
}
- let i = ~100;
- let j = ~100;
+ let i = box 100;
+ let j = box 100;
f(i, j);
- let i = ~100;
- let j = ~101;
+ let i = box 100;
+ let j = box 101;
g(i, j);
}
assert!(i != j);
}
- let i = ~100;
- let j = ~100;
+ let i = box 100;
+ let j = box 100;
f(i, j);
- let i = ~100;
- let j = ~101;
+ let i = box 100;
+ let j = box 101;
g(i, j);
}
// except according to those terms.
pub fn main() {
- let i = ~100;
+ let i = box 100;
println!("{:?}", i);
}
// Issue #961
fn altsimple() {
- match ~true {
+ match box true {
_ => { }
}
}
#![allow(unused_variable)]
pub fn main() {
- let i = ~100;
- let j = ~200;
+ let i = box 100;
+ let j = box 200;
let j = i;
assert_eq!(*j, 100);
}
pub fn main() {
let mut i;
- i = ~100;
+ i = box 100;
assert_eq!(*i, 100);
}
// except according to those terms.
pub fn main() {
- let i = ~100;
+ let i = box 100;
let mut j;
j = i;
assert_eq!(*j, 100);
// except according to those terms.
pub fn main() {
- let mut i = ~0;
+ let mut i = box 0;
*i = 1;
assert_eq!(*i, 1);
}
// Issue #5192
+
pub trait EventLoop { }
pub struct UvEventLoop {
impl EventLoop for UvEventLoop { }
pub fn main() {
- let loop_: ~EventLoop = ~UvEventLoop { uvio: 0 } as ~EventLoop;
+ let loop_: Box<EventLoop> = box UvEventLoop { uvio: 0 } as Box<EventLoop>;
let _loop2_ = loop_;
}
struct Foo {a: int, b: uint}
-enum bar { u(~Foo), w(int), }
+enum bar { u(Box<Foo>), w(int), }
pub fn main() {
- assert!(match u(~Foo{a: 10, b: 40u}) {
- u(~Foo{a: a, b: b}) => { a + (b as int) }
+ assert!(match u(box Foo{a: 10, b: 40u}) {
+ u(box Foo{a: a, b: b}) => { a + (b as int) }
_ => { 66 }
} == 50);
}
// except according to those terms.
-enum bar { u(~int), w(int), }
+enum bar { u(Box<int>), w(int), }
pub fn main() {
- assert!(match u(~10) {
+ assert!(match u(box 10) {
u(a) => {
println!("{:?}", a);
*a
// except according to those terms.
fn simple() {
- match ~true {
- ~true => { }
+ match box true {
+ box true => { }
_ => { fail!(); }
}
}
struct X { x: int }
pub fn main() {
- let x = ~X {x: 1};
+ let x = box X {x: 1};
let bar = x;
assert_eq!(bar.x, 1);
}
use std::task;
-fn child(tx: &Sender<~uint>, i: uint) {
- tx.send(~i);
+fn child(tx: &Sender<Box<uint>>, i: uint) {
+ tx.send(box i);
}
pub fn main() {
pub fn main() {
let (tx, rx) = channel();
- tx.send(~100);
+ tx.send(box 100);
let v = rx.recv();
- assert_eq!(v, ~100);
+ assert_eq!(v, box 100);
}
use std::mem::swap;
pub fn main() {
- let mut i = ~100;
- let mut j = ~200;
+ let mut i = box 100;
+ let mut j = box 200;
swap(&mut i, &mut j);
- assert_eq!(i, ~200);
- assert_eq!(j, ~100);
+ assert_eq!(i, box 200);
+ assert_eq!(j, box 100);
}
// except according to those terms.
#![feature(struct_variant)]
+
// Test sized-ness checking in substitution.
// Unbounded.
// Self type.
trait T2 for type {
- fn f() -> ~Self;
+ fn f() -> Box<Self>;
}
struct S;
impl T2 for S {
- fn f() -> ~S {
- ~S
+ fn f() -> Box<S> {
+ box S
}
}
fn f5<type X: T2>(x: &X) {
- let _: ~X = T2::f();
+ let _: Box<X> = T2::f();
}
fn f6<X: T2>(x: &X) {
- let _: ~X = T2::f();
+ let _: Box<X> = T2::f();
}
trait T3 for type {
- fn f() -> ~Self;
+ fn f() -> Box<Self>;
}
impl T3 for S {
- fn f() -> ~S {
- ~S
+ fn f() -> Box<S> {
+ box S
}
}
fn f7<type X: T3>(x: &X) {
// This is valid, but the unsized bound on X is irrelevant because any type
// which implements T3 must have statically known size.
- let _: ~X = T3::f();
+ let _: Box<X> = T3::f();
}
trait T4<X> {
// except according to those terms.
pub fn main() {
- let _x = ~1;
+ let _x = box 1;
let lam_move: || = || {};
lam_move();
}
pub fn main()
{
- let y = ~1;
+ let y = box 1;
y;
}
use std::task;
fn f() {
- let _a = ~0;
+ let _a = box 0;
fail!();
}