<commit_before>/*!
Pattern-based input scanning.

## Setup

First, place the following in your `Cargo.toml` file:

```{notrust}
[dependencies.scan]

git = "https://github.com/DanielKeep/rust-scan.git"

[dependencies.scan_util]

git = "https://github.com/DanielKeep/rust-scan-util.git"
```

If you are not using Cargo, you will need to download and compile both of these crates and make them available to `rustc`.  Note that the `scan` crate is *only* needed at compile time and does not need to be distributed.

Then, in your root module, add the following:

```{ignore}
#![feature(phase)]

#[phase(plugin)] extern crate scan;
extern crate scan_util;
```

Note that `scan_util` *must* be in the root module, and *must* not be renamed.  This is due to a limitation of macros in Rust.

## Usage

Two macros are provided for scanning text.  In general, both are concerned with taking a string and matching it against a sequence of patterns.  As soon as a matching pattern is found, the corresponding expression is evaluated and returned.

If an error occurs during an underlying IO operation *or* none of the provided patterns matched, an `Err(scan_util::ScanError)` will be returned.

The `scanln!` macro is used to scan a line of input from standard input.  For example:

```{ignore}
scanln! {
	"say hello" => println!("Hi!"),
	"exit" => return,
}
```

The `scan!` macro is used to scan a block of text.  The input value must implement the `Str` trait.  For example:

```{ignore}
let noun_to_identify = "wheelbarrow";
scan! {
	noun_to_identify,

	"banana" => "definitely a banana",
	"crowbar" => "big metal banana",
	_ => "probably not a banana at all",
}
```

## Patterns

A pattern is a space-separated sequence of one or more of the following:

### Text

These indicate a block of text which should be matched.  This matching is done by converting *both* text in the pattern *and* input text into a sequence of tokens, ignoring whitespace.  Each token is either a sequence of letters, a sequence of digits, or a single non-whitespace character.  All whitespace is ignored.

For example, the string `"Left4Dead is pretty fun..."` is tokenised into the sequence `"Left"`, `"4"`, `"Dead"`, `"is"`, `"pretty"`, `"fun"`, `"."`, `"."`, and `"."`.

This behaviour also means that `"ab cd ef"` and `"ab" "cd" "ef"` are semantically equivalent, but `"ab c" "d ef"` is different, because of the break between `c` and `d`.

Also note that text comparisons are *case insensitive*.

In future, the tokeniser, whitespace policy, and case insensitivity will be configurable.

### Capture

These are used to capture a value from the input.  They are written in the form `name: type` like a `let` binding.  The type constraint (`:type`) may be omitted *if* the usage of the captured value allows the type to be inferred.

For example, `age:int` will capture an integer and store it in a binding called `age`.  `thingy` will capture a value, the type of which is to be determined by inference.

An additional restriction is that you can only capture types which implement the `scan_util::Scanner` trait.  By default, scanners for the builtin integer and floating-point types are available as well as `bool` and `char`.  There is also a scanner for `&str` which will capture a single token.

If you wish to supply your own scanning logic for a type, you will need to wrap it in another type (such as a structure) and implement the `Scanner` trait.

### Alternate

A pattern written as `"a" | "b"` will match *either* `a` or `b`.  You can chain as many alternates as you want.

Note that alternates are tried in lexical order, and the first one to match "wins" and no others are tried.  For example, in the pattern `"a" | "a b"`, the second branch will never match.  Also note that as the scanner does not do backtracking, a failure to match later on in a pattern will not cause other alternatives to be tried.

All captures inside an alternate are wrapped in `Option`, with unmatched captures being `None`.

### Group

You can create a sub pattern using parentheses.  This is mainly used for grouping alternates.  For example: `"a" ("b" | "c") "d"`; this will match `a b d` or `a c d`.

### Repetition

Reptitions are used to match a repeating sequence, and optionally capture values from said sequence.  The general form is `[pattern] separator repeat`.

For example:

* `["pretty"]+ "please"` - matches a childish plea.

* `"rgb (" [cs:f32],{3} ")"` - matches a CSS `rgb` colour value.

* `[ns:int](ws:&str)+` - matches a sequence of at least one number separated by arbitrary words.

The `separator` is used to indicate what to match between instances of the main repeating `pattern`.  It can be omitted (in which case no seperator is scanned), or a sub pattern.  A sub pattern consisting of a single text literal can be written with the parentheses omitted.  If the text literal is `","`, `"."`, `";"`, or `":"`, then it may be written without the quotes as well.

The `repeat` indicates how many times the repeating `pattern` must appear.  It can be any one of:

- `?` - zero or one times.

- `*` - zero or more times.

- `+` - one or more times.

- `{n}` - exactly `n` times.

- `{n,}` - at least `n` times.

- `{,m}` - zero or more, but no more than `m`, times.

- `{n,m}` - at least `n`, but no more than `m`, times.

All captures inside a repetition are inserted into `Vec`s.  Nesting repetitions yield nested `Vec`s.

### Tail Capture

Patterns must match their *entire* input.  If you only wish to perform a prefix match, you must add a tail capture to the pattern.  For example, `"spake thee thus", ..the_rest` would match "spake thee thus" and then capture the remainder of the input into `the_rest`.  Note the comma to distinguish the tail capture from the pattern.  Also note that tail captures are `&str`s, limited to the lifetime of the input.

If you wish to do a prefix match, but do not actually care about the remainder of the input, you can use `_` as the capture name.

### Fallback Pattern

Finally, you can specify a fallback arm which *always* matches.  The complete pattern should be either a tail capture (such as `..tail` without any preceeding pattern), or a simple `_`.

## Example

Below is a complete example of various kinds of patterns.

```{ignore}
#![feature(phase)]

#[phase(plugin)] extern crate scan;
extern crate scan_util;

fn main() {
	loop {
		print!("input> ");

		let res = scanln! {
			// Match a single word.
			"hi" => "Hi!".into_string(),

			// Match a sequence of three tokens: "such", "input" and "!".
			"such input!" => "very syntax".into_string(),

			// Match *five* tokens: "and", "now", ".", "." and ".".
			"and now..." => "...for something completely different".into_string(),

			// Match "has" followed by an integer, captured into "value".
			"has" value:int => format!("ok has {}", value),

			// Alternative to the above.
			"has also" value => {
				let value: int = value;
				format!("ok has also {}", value)
			},

			// Match "v" followed by three numbers.
			"v" x:f64 y:f64 z:f64 => format!("({}, {}, {})", x, y, z),

			// Match "rgb" followed by three numbers.
			"rgb" r:u8 g:u8 b:u8 => format!("#{:02x}{:02x}{:02x}", r, g, b),

			// Match "rgb vec" followed by three or four numbers.
			"rgb vec" [rgb:u8],{3,4} => format!("rgba{}", rgb),

			// Match "vecs" followed by a comma-delimited vector of
			// comma-delimited vectors of floats.
			("vecs"|"vechs"|"vetches") [ "[" [vss:f64],* "]" ],* => format!("vss: {}", vss),

			// Match a vector of either an int or a word.
			"ints and words:" [is:int | ss:&str]* => format!("is: {}, ss: {}", is, ss),

			// Match a list of words separated by "and" or a comma.
			"words:" [words:&str]("and"|", and"|",")+ => format!("words: {}", words),

			// Match a list of numbers separated by words.
			"int words:" [is:int](ss:&str)* => format!("is: {}, ss: {}", is, ss),

			// Match "go" followed by a single word.
			"go" exit:&str => format!("Leaving by the {} exit.", exit),

			// Match "yes" or "no".
			"yes" | "no" => "maybe yup".into_string(),

			// Match an integer or a float.
			"i" i:int | "f" f:f64 => format!("i {} | f {}", i, f),

			// Match "identify", with the remainder of the input captured by "tail".
			"identify", ..tail => identify_banana(tail).into_string(),

			// Exit this loop.
			"exit" | "quit" => break,

			// If no other arm else matches, capture all the input into "tail".
			// You could also use `_` as the pattern, if you don't care about the
			// actual input.  Note that this will also swallow any errors caused
			// by previous arms not matching.
			//..tail => format!("wow {}", tail),
		};

		match res {
			Ok(value) => println!("Ok: {}", value),
			Err(err) => println!("Err: {}", err)
		}
	}
}

fn identify_banana<S: Str>(s: S) -> &'static str {
	(scan! {
		s,
		"banana" => "definitely a banana",
		"crowbar" => "giant metal banana",
		"human finger" => "tiny crunchy banana",
		_ => "probably not a banana"
	}).unwrap()
}
```
*/
#![feature(managed_boxes)]
#![feature(phase)]
#![feature(plugin_registrar)]
#![feature(quote)]
#![feature(struct_variant)]

#[phase(plugin, link)] extern crate log;
extern crate rustc;
extern crate syntax;

extern crate scan_util;

pub mod parse;
pub mod plugin;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut rustc::plugin::Registry) {
	reg.register_macro("scan", plugin::expand_scan);
	reg.register_macro("scanln", plugin::expand_scanln);
}
<commit_msg>Updated to latest rustc nightly.<commit_after>/*!
Pattern-based input scanning.

## Setup

First, place the following in your `Cargo.toml` file:

```{notrust}
[dependencies.scan]

git = "https://github.com/DanielKeep/rust-scan.git"

[dependencies.scan_util]

git = "https://github.com/DanielKeep/rust-scan-util.git"
```

If you are not using Cargo, you will need to download and compile both of these crates and make them available to `rustc`.  Note that the `scan` crate is *only* needed at compile time and does not need to be distributed.

Then, in your root module, add the following:

```{ignore}
#![feature(phase)]

#[phase(plugin)] extern crate scan;
extern crate scan_util;
```

Note that `scan_util` *must* be in the root module, and *must* not be renamed.  This is due to a limitation of macros in Rust.

## Usage

Two macros are provided for scanning text.  In general, both are concerned with taking a string and matching it against a sequence of patterns.  As soon as a matching pattern is found, the corresponding expression is evaluated and returned.

If an error occurs during an underlying IO operation *or* none of the provided patterns matched, an `Err(scan_util::ScanError)` will be returned.

The `scanln!` macro is used to scan a line of input from standard input.  For example:

```{ignore}
scanln! {
	"say hello" => println!("Hi!"),
	"exit" => return,
}
```

The `scan!` macro is used to scan a block of text.  The input value must implement the `Str` trait.  For example:

```{ignore}
let noun_to_identify = "wheelbarrow";
scan! {
	noun_to_identify,

	"banana" => "definitely a banana",
	"crowbar" => "big metal banana",
	_ => "probably not a banana at all",
}
```

## Patterns

A pattern is a space-separated sequence of one or more of the following:

### Text

These indicate a block of text which should be matched.  This matching is done by converting *both* text in the pattern *and* input text into a sequence of tokens, ignoring whitespace.  Each token is either a sequence of letters, a sequence of digits, or a single non-whitespace character.  All whitespace is ignored.

For example, the string `"Left4Dead is pretty fun..."` is tokenised into the sequence `"Left"`, `"4"`, `"Dead"`, `"is"`, `"pretty"`, `"fun"`, `"."`, `"."`, and `"."`.

This behaviour also means that `"ab cd ef"` and `"ab" "cd" "ef"` are semantically equivalent, but `"ab c" "d ef"` is different, because of the break between `c` and `d`.

Also note that text comparisons are *case insensitive*.

In future, the tokeniser, whitespace policy, and case insensitivity will be configurable.

### Capture

These are used to capture a value from the input.  They are written in the form `name: type` like a `let` binding.  The type constraint (`:type`) may be omitted *if* the usage of the captured value allows the type to be inferred.

For example, `age:int` will capture an integer and store it in a binding called `age`.  `thingy` will capture a value, the type of which is to be determined by inference.

An additional restriction is that you can only capture types which implement the `scan_util::Scanner` trait.  By default, scanners for the builtin integer and floating-point types are available as well as `bool` and `char`.  There is also a scanner for `&str` which will capture a single token.

If you wish to supply your own scanning logic for a type, you will need to wrap it in another type (such as a structure) and implement the `Scanner` trait.

### Alternate

A pattern written as `"a" | "b"` will match *either* `a` or `b`.  You can chain as many alternates as you want.

Note that alternates are tried in lexical order, and the first one to match "wins" and no others are tried.  For example, in the pattern `"a" | "a b"`, the second branch will never match.  Also note that as the scanner does not do backtracking, a failure to match later on in a pattern will not cause other alternatives to be tried.

All captures inside an alternate are wrapped in `Option`, with unmatched captures being `None`.

### Group

You can create a sub pattern using parentheses.  This is mainly used for grouping alternates.  For example: `"a" ("b" | "c") "d"`; this will match `a b d` or `a c d`.

### Repetition

Reptitions are used to match a repeating sequence, and optionally capture values from said sequence.  The general form is `[pattern] separator repeat`.

For example:

* `["pretty"]+ "please"` - matches a childish plea.

* `"rgb (" [cs:f32],{3} ")"` - matches a CSS `rgb` colour value.

* `[ns:int](ws:&str)+` - matches a sequence of at least one number separated by arbitrary words.

The `separator` is used to indicate what to match between instances of the main repeating `pattern`.  It can be omitted (in which case no seperator is scanned), or a sub pattern.  A sub pattern consisting of a single text literal can be written with the parentheses omitted.  If the text literal is `","`, `"."`, `";"`, or `":"`, then it may be written without the quotes as well.

The `repeat` indicates how many times the repeating `pattern` must appear.  It can be any one of:

- `?` - zero or one times.

- `*` - zero or more times.

- `+` - one or more times.

- `{n}` - exactly `n` times.

- `{n,}` - at least `n` times.

- `{,m}` - zero or more, but no more than `m`, times.

- `{n,m}` - at least `n`, but no more than `m`, times.

All captures inside a repetition are inserted into `Vec`s.  Nesting repetitions yield nested `Vec`s.

### Tail Capture

Patterns must match their *entire* input.  If you only wish to perform a prefix match, you must add a tail capture to the pattern.  For example, `"spake thee thus", ..the_rest` would match "spake thee thus" and then capture the remainder of the input into `the_rest`.  Note the comma to distinguish the tail capture from the pattern.  Also note that tail captures are `&str`s, limited to the lifetime of the input.

If you wish to do a prefix match, but do not actually care about the remainder of the input, you can use `_` as the capture name.

### Fallback Pattern

Finally, you can specify a fallback arm which *always* matches.  The complete pattern should be either a tail capture (such as `..tail` without any preceeding pattern), or a simple `_`.

## Example

Below is a complete example of various kinds of patterns.

```{ignore}
#![feature(phase)]

#[phase(plugin)] extern crate scan;
extern crate scan_util;

fn main() {
	loop {
		print!("input> ");

		let res = scanln! {
			// Match a single word.
			"hi" => "Hi!".into_string(),

			// Match a sequence of three tokens: "such", "input" and "!".
			"such input!" => "very syntax".into_string(),

			// Match *five* tokens: "and", "now", ".", "." and ".".
			"and now..." => "...for something completely different".into_string(),

			// Match "has" followed by an integer, captured into "value".
			"has" value:int => format!("ok has {}", value),

			// Alternative to the above.
			"has also" value => {
				let value: int = value;
				format!("ok has also {}", value)
			},

			// Match "v" followed by three numbers.
			"v" x:f64 y:f64 z:f64 => format!("({}, {}, {})", x, y, z),

			// Match "rgb" followed by three numbers.
			"rgb" r:u8 g:u8 b:u8 => format!("#{:02x}{:02x}{:02x}", r, g, b),

			// Match "rgb vec" followed by three or four numbers.
			"rgb vec" [rgb:u8],{3,4} => format!("rgba{}", rgb),

			// Match "vecs" followed by a comma-delimited vector of
			// comma-delimited vectors of floats.
			("vecs"|"vechs"|"vetches") [ "[" [vss:f64],* "]" ],* => format!("vss: {}", vss),

			// Match a vector of either an int or a word.
			"ints and words:" [is:int | ss:&str]* => format!("is: {}, ss: {}", is, ss),

			// Match a list of words separated by "and" or a comma.
			"words:" [words:&str]("and"|", and"|",")+ => format!("words: {}", words),

			// Match a list of numbers separated by words.
			"int words:" [is:int](ss:&str)* => format!("is: {}, ss: {}", is, ss),

			// Match "go" followed by a single word.
			"go" exit:&str => format!("Leaving by the {} exit.", exit),

			// Match "yes" or "no".
			"yes" | "no" => "maybe yup".into_string(),

			// Match an integer or a float.
			"i" i:int | "f" f:f64 => format!("i {} | f {}", i, f),

			// Match "identify", with the remainder of the input captured by "tail".
			"identify", ..tail => identify_banana(tail).into_string(),

			// Exit this loop.
			"exit" | "quit" => break,

			// If no other arm else matches, capture all the input into "tail".
			// You could also use `_` as the pattern, if you don't care about the
			// actual input.  Note that this will also swallow any errors caused
			// by previous arms not matching.
			//..tail => format!("wow {}", tail),
		};

		match res {
			Ok(value) => println!("Ok: {}", value),
			Err(err) => println!("Err: {}", err)
		}
	}
}

fn identify_banana<S: Str>(s: S) -> &'static str {
	(scan! {
		s,
		"banana" => "definitely a banana",
		"crowbar" => "giant metal banana",
		"human finger" => "tiny crunchy banana",
		_ => "probably not a banana"
	}).unwrap()
}
```
*/
#![feature(phase)]
#![feature(plugin_registrar)]
#![feature(quote)]
#![feature(struct_variant)]

#[phase(plugin, link)] extern crate log;
extern crate rustc;
extern crate syntax;

extern crate scan_util;

pub mod parse;
pub mod plugin;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut rustc::plugin::Registry) {
	reg.register_macro("scan", plugin::expand_scan);
	reg.register_macro("scanln", plugin::expand_scanln);
}
<|endoftext|>


<commit_before>#![crate_name = "sqlite3"]
#![crate_type = "lib"]
#![feature(unsafe_destructor)]

extern crate libc;

use libc::c_int;
use std::num::from_uint;
use std::ptr;

#[allow(non_camel_case_types, dead_code)]
mod ffi;

pub struct SqliteConnection {
    // not pub so that nothing outside this module
    // interferes with the lifetime
    db: *mut ffi::sqlite3
}

impl Drop for SqliteConnection {
    fn drop(&mut self) {
        let ok = unsafe { ffi::sqlite3_close_v2(self.db) };
        assert_eq!(ok, SQLITE_OK as c_int);
    }
}

impl SqliteConnection {
    // Create a new connection to an in-memory database.
    // TODO: explicit access to files
    // TODO: use support _v2 interface with flags
    // TODO: integrate sqlite3_errmsg()
    pub fn new() -> Result<SqliteConnection, SqliteError> {
        let mut db = ptr::mut_null();
        let result = ":memory:".with_c_str({
            |memory|
            unsafe { ffi::sqlite3_open(memory, &mut db) }
        });
        match decode_result(result, "sqlite3_open") {
            Ok(()) => Ok(SqliteConnection { db: db }),
            Err(err) => {
                // "Whether or not an error occurs when it is opened,
                // resources associated with the database connection
                // handle should be released by passing it to
                // sqlite3_close() when it is no longer required."
                unsafe { ffi::sqlite3_close_v2(db) };
                Err(err)
            }
        }
    }

    /// Prepare/compile an SQL statement.
    /// See http://www.sqlite.org/c3ref/prepare.html
    pub fn prepare<'db>(&'db mut self, sql: &str) -> SqliteResult<SqliteStatement<'db>> {
        match self.prepare_with_offset(sql) {
            Ok((cur, _)) => Ok(cur),
            Err(e) => Err(e)
        }
    }

    pub fn prepare_with_offset<'db>(&'db mut self, sql: &str) -> SqliteResult<(SqliteStatement<'db>, uint)> {
        let mut stmt = ptr::mut_null();
        let mut tail = ptr::null();
        let z_sql = sql.as_ptr() as *const ::libc::c_char;
        let n_byte = sql.len() as c_int;
        let r = unsafe { ffi::sqlite3_prepare_v2(self.db, z_sql, n_byte, &mut stmt, &mut tail) };
        match decode_result(r, "sqlite3_prepare_v2") {
            Ok(()) => {
                let offset = tail as uint - z_sql as uint;
                Ok((SqliteStatement::new(stmt), offset))
            },
            Err(code) => Err(code)
        }
    }

}

pub struct SqliteStatement<'db> {
    stmt: *mut ffi::sqlite3_stmt
}

#[unsafe_destructor]
impl<'db> Drop for SqliteStatement<'db> {
    fn drop(&mut self) {
        unsafe {

            // We ignore the return code from finalize because:

            // "If If the most recent evaluation of statement S
            // failed, then sqlite3_finalize(S) returns the
            // appropriate error codethe most recent evaluation of
            // statement S failed, then sqlite3_finalize(S) returns
            // the appropriate error code"

            // "The sqlite3_finalize(S) routine can be called at any
            // point during the life cycle of prepared statement S"

            ffi::sqlite3_finalize(self.stmt);
        }
    }
}

impl<'db> SqliteStatement<'db> {
    // Only a SqliteCursor can call this constructor
    #[allow(visible_private_types)]
    pub fn new<'db>(stmt: *mut ffi::sqlite3_stmt) -> SqliteStatement<'db> {
        SqliteStatement { stmt: stmt }
    }
}

// ref http://www.sqlite.org/c3ref/c_abort.html
#[deriving(Show, PartialEq, Eq, FromPrimitive)]
#[allow(non_camel_case_types)]
enum SqliteOk {
    SQLITE_OK = 0
}

#[must_use]
pub type SqliteResult<T> = Result<T, SqliteError>;

#[deriving(Show, PartialEq, Eq, FromPrimitive)]
#[allow(non_camel_case_types)]
pub enum SqliteError {
    SQLITE_ERROR     =  1,
    SQLITE_INTERNAL  =  2,
    SQLITE_PERM      =  3,
    SQLITE_ABORT     =  4,
    SQLITE_BUSY      =  5,
    SQLITE_LOCKED    =  6,
    SQLITE_NOMEM     =  7,
    SQLITE_READONLY  =  8,
    SQLITE_INTERRUPT =  9,
    SQLITE_IOERR     = 10,
    SQLITE_CORRUPT   = 11,
    SQLITE_NOTFOUND  = 12,
    SQLITE_FULL      = 13,
    SQLITE_CANTOPEN  = 14,
    SQLITE_PROTOCOL  = 15,
    SQLITE_EMPTY     = 16,
    SQLITE_SCHEMA    = 17,
    SQLITE_TOOBIG    = 18,
    SQLITE_CONSTRAINT= 19,
    SQLITE_MISMATCH  = 20,
    SQLITE_MISUSE    = 21,
    SQLITE_NOLFS     = 22,
    SQLITE_AUTH      = 23,
    SQLITE_FORMAT    = 24,
    SQLITE_RANGE     = 25,
    SQLITE_NOTADB    = 26
}

#[inline]
pub fn decode_result(result: c_int, context: &str) -> SqliteResult<()> {
    if result == SQLITE_OK as c_int {
        Ok(())
    } else {
        match from_uint::<SqliteError>(result as uint) {
            Some(code) => Err(code),
            None => fail!("{} returned unexpected {:d}", context, result)
        }
    }
}

#[deriving(Show, PartialEq, Eq, FromPrimitive)]
#[allow(non_camel_case_types)]
pub enum SqliteLogLevel {
    SQLITE_NOTICE    = 27,
    SQLITE_WARNING   = 28,
}

#[deriving(Show, PartialEq, Eq, FromPrimitive)]
#[allow(non_camel_case_types)]
enum SqliteStep {
    SQLITE_ROW       = 100,
    SQLITE_DONE      = 101,
}

#[cfg(test)]
mod tests {
    use super::{SqliteConnection, SqliteResult};

    #[test]
    fn db_new_types() {
        SqliteConnection::new().unwrap();
    }

    #[test]
    fn stmt_new_types() {
        fn go() -> SqliteResult<()> {
            let mut db = try!(SqliteConnection::new());
            db.prepare("select 1 + 1").map( |_s| () )
        }
        go().unwrap();
    }
}
<commit_msg>query() iterates over rows (though doesn't give access to columns)<commit_after>#![crate_name = "sqlite3"]
#![crate_type = "lib"]
#![feature(unsafe_destructor)]

extern crate libc;

use libc::c_int;
use std::num::from_uint;
use std::ptr;

#[allow(non_camel_case_types, dead_code)]
mod ffi;

pub struct SqliteConnection {
    // not pub so that nothing outside this module
    // interferes with the lifetime
    db: *mut ffi::sqlite3
}

impl Drop for SqliteConnection {
    fn drop(&mut self) {
        let ok = unsafe { ffi::sqlite3_close_v2(self.db) };
        assert_eq!(ok, SQLITE_OK as c_int);
    }
}

impl SqliteConnection {
    // Create a new connection to an in-memory database.
    // TODO: explicit access to files
    // TODO: use support _v2 interface with flags
    // TODO: integrate sqlite3_errmsg()
    pub fn new() -> Result<SqliteConnection, SqliteError> {
        let mut db = ptr::mut_null();
        let result = ":memory:".with_c_str({
            |memory|
            unsafe { ffi::sqlite3_open(memory, &mut db) }
        });
        match decode_result(result, "sqlite3_open") {
            Ok(()) => Ok(SqliteConnection { db: db }),
            Err(err) => {
                // "Whether or not an error occurs when it is opened,
                // resources associated with the database connection
                // handle should be released by passing it to
                // sqlite3_close() when it is no longer required."
                unsafe { ffi::sqlite3_close_v2(db) };
                Err(err)
            }
        }
    }

    /// Prepare/compile an SQL statement.
    /// See http://www.sqlite.org/c3ref/prepare.html
    pub fn prepare<'db>(&'db mut self, sql: &str) -> SqliteResult<SqliteStatement<'db>> {
        match self.prepare_with_offset(sql) {
            Ok((cur, _)) => Ok(cur),
            Err(e) => Err(e)
        }
    }

    pub fn prepare_with_offset<'db>(&'db mut self, sql: &str) -> SqliteResult<(SqliteStatement<'db>, uint)> {
        let mut stmt = ptr::mut_null();
        let mut tail = ptr::null();
        let z_sql = sql.as_ptr() as *const ::libc::c_char;
        let n_byte = sql.len() as c_int;
        let r = unsafe { ffi::sqlite3_prepare_v2(self.db, z_sql, n_byte, &mut stmt, &mut tail) };
        match decode_result(r, "sqlite3_prepare_v2") {
            Ok(()) => {
                let offset = tail as uint - z_sql as uint;
                Ok((SqliteStatement::new(stmt), offset))
            },
            Err(code) => Err(code)
        }
    }

}

pub struct SqliteStatement<'db> {
    stmt: *mut ffi::sqlite3_stmt
}

#[unsafe_destructor]
impl<'db> Drop for SqliteStatement<'db> {
    fn drop(&mut self) {
        unsafe {

            // We ignore the return code from finalize because:

            // "If If the most recent evaluation of statement S
            // failed, then sqlite3_finalize(S) returns the
            // appropriate error codethe most recent evaluation of
            // statement S failed, then sqlite3_finalize(S) returns
            // the appropriate error code"

            // "The sqlite3_finalize(S) routine can be called at any
            // point during the life cycle of prepared statement S"

            ffi::sqlite3_finalize(self.stmt);
        }
    }
}

impl<'db> SqliteStatement<'db> {
    // Only a SqliteCursor can call this constructor
    #[allow(visible_private_types)]
    pub fn new<'db>(stmt: *mut ffi::sqlite3_stmt) -> SqliteStatement<'db> {
        SqliteStatement { stmt: stmt }
    }

    pub fn query(&mut self) -> SqliteResult<SqliteRows> {
        {
            let r = unsafe { ffi::sqlite3_reset(self.stmt) };
            try!(decode_result(r, "sqlite3_reset"))
        }
        Ok(SqliteRows::new(self))
    }
}

pub struct SqliteRows<'s> {
    statement: &'s mut SqliteStatement<'s>,
}

impl<'s> SqliteRows<'s> {
    pub fn new(statement: &'s mut SqliteStatement) -> SqliteRows<'s> {
        SqliteRows { statement: statement }
    }
}

impl<'s> Iterator<SqliteResult<()>> for SqliteRows<'s> {
    fn next(&mut self) -> Option<SqliteResult<()>> {
        let r = unsafe { ffi::sqlite3_step(self.statement.stmt) } as uint;
        match from_uint::<SqliteStep>(r) {
            Some(SQLITE_ROW) => Some(Ok(())),
            Some(SQLITE_DONE) => None,
            None => {
                let err = from_uint::<SqliteError>(r);
                Some(Err(err.unwrap()))
            }
        }
    }
}

// ref http://www.sqlite.org/c3ref/c_abort.html
#[deriving(Show, PartialEq, Eq, FromPrimitive)]
#[allow(non_camel_case_types)]
enum SqliteOk {
    SQLITE_OK = 0
}

#[must_use]
pub type SqliteResult<T> = Result<T, SqliteError>;

#[deriving(Show, PartialEq, Eq, FromPrimitive)]
#[allow(non_camel_case_types)]
pub enum SqliteError {
    SQLITE_ERROR     =  1,
    SQLITE_INTERNAL  =  2,
    SQLITE_PERM      =  3,
    SQLITE_ABORT     =  4,
    SQLITE_BUSY      =  5,
    SQLITE_LOCKED    =  6,
    SQLITE_NOMEM     =  7,
    SQLITE_READONLY  =  8,
    SQLITE_INTERRUPT =  9,
    SQLITE_IOERR     = 10,
    SQLITE_CORRUPT   = 11,
    SQLITE_NOTFOUND  = 12,
    SQLITE_FULL      = 13,
    SQLITE_CANTOPEN  = 14,
    SQLITE_PROTOCOL  = 15,
    SQLITE_EMPTY     = 16,
    SQLITE_SCHEMA    = 17,
    SQLITE_TOOBIG    = 18,
    SQLITE_CONSTRAINT= 19,
    SQLITE_MISMATCH  = 20,
    SQLITE_MISUSE    = 21,
    SQLITE_NOLFS     = 22,
    SQLITE_AUTH      = 23,
    SQLITE_FORMAT    = 24,
    SQLITE_RANGE     = 25,
    SQLITE_NOTADB    = 26
}

#[inline]
pub fn decode_result(result: c_int, context: &str) -> SqliteResult<()> {
    if result == SQLITE_OK as c_int {
        Ok(())
    } else {
        match from_uint::<SqliteError>(result as uint) {
            Some(code) => Err(code),
            None => fail!("{} returned unexpected {:d}", context, result)
        }
    }
}

#[deriving(Show, PartialEq, Eq, FromPrimitive)]
#[allow(non_camel_case_types)]
pub enum SqliteLogLevel {
    SQLITE_NOTICE    = 27,
    SQLITE_WARNING   = 28,
}

#[deriving(Show, PartialEq, Eq, FromPrimitive)]
#[allow(non_camel_case_types)]
enum SqliteStep {
    SQLITE_ROW       = 100,
    SQLITE_DONE      = 101,
}

#[cfg(test)]
mod tests {
    use super::{SqliteConnection, SqliteResult};

    #[test]
    fn db_new_types() {
        SqliteConnection::new().unwrap();
    }

    #[test]
    fn stmt_new_types() {
        fn go() -> SqliteResult<()> {
            let mut db = try!(SqliteConnection::new());
            db.prepare("select 1 + 1").map( |_s| () )
        }
        go().unwrap();
    }

    #[test]
    fn query_two_rows() {
        fn go() -> SqliteResult<uint> {
            let mut count = 0;

            let mut db = try!(SqliteConnection::new());
            let mut s = try!(db.prepare("select 1 union all select 2"));
            for row in try!(s.query()) {
                count += 1
            }
            Ok(count)
        }
        assert_eq!(go(), Ok(2))
    }
}
<|endoftext|>


<commit_before>extern crate hyper;

pub mod requests;

#[cfg(test)]
mod test {
    use super::requests;
    use hyper::status::StatusCode;

    #[test]
    fn test_get() {
        const URL: &'static str = "http://httpbin.org/get";
        let res = requests::get(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_post() {
        const URL: &'static str = "http://httpbin.org/post";
        let res = requests::post(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_put() {
        const URL: &'static str = "http://httpbin.org/put";
        let res = requests::put(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_head() {
        const URL: &'static str = "http://httpbin.org/get";
        let res = requests::head(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_delete() {
        const URL: &'static str = "http://httpbin.org/delete";
        let res = requests::delete(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }
}
<commit_msg>Add useragent test<commit_after>extern crate hyper;

pub mod requests;

#[cfg(test)]
mod test {
    use super::requests;
    use hyper::status::StatusCode;

    #[test]
    fn test_get() {
        const URL: &'static str = "http://httpbin.org/get";
        let res = requests::get(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_post() {
        const URL: &'static str = "http://httpbin.org/post";
        let res = requests::post(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_put() {
        const URL: &'static str = "http://httpbin.org/put";
        let res = requests::put(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_head() {
        const URL: &'static str = "http://httpbin.org/get";
        let res = requests::head(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_delete() {
        const URL: &'static str = "http://httpbin.org/delete";
        let res = requests::delete(URL).unwrap();
        assert_eq!(res.url(), URL);
        assert_eq!(res.status_code(), StatusCode::Ok);
        assert_eq!(res.reason(), "OK");
    }

    #[test]
    fn test_user_agent() {
        const URL: &'static str = "http://httpbin.org/user-agent";
        let res = requests::get(URL).unwrap();
        println!("{:?}", res.text());
        assert_eq!(res.reason(), "Ok");
    }
}
<|endoftext|>


<commit_before>use crate::chip::Chip;
use crate::database::Database;
use std::collections::HashMap;

use crate::bba::idstring::*;
use crate::bba::idxset::*;
use crate::bba::tiletype::TileTypes;

// A tile type from the interchange format perspective
// this is not the same as a database tile type; because the Oxide graph can have
// more than one tile at a grid location whereas the interchange grid is one tile
// per location

#[derive(Clone, Eq, PartialEq, Hash)]
pub struct TileTypeKey {
    pub tile_types: Vec<String>,
}
impl TileTypeKey {
    pub fn new() -> TileTypeKey {
        TileTypeKey { tile_types: Vec::new() }
    }
}

pub struct IcTileType {
    key: TileTypeKey,
    wires: IndexedMap<IdString, IcWire>,
    pips: Vec<IcPip>,
    // TODO: constants, sites, etc
}

impl IcTileType {
    pub fn new(key: TileTypeKey) -> IcTileType {
        IcTileType {
            key: key,
            wires: IndexedMap::new(),
            pips: Vec::new(),
        }
    }
    pub fn wire(&mut self, name: IdString) -> usize {
        self.wires.add(&name, IcWire::new(name))
    }
}

pub struct IcWire {
    name: IdString,
    pips_uphill: Vec<usize>,
    pips_downhill: Vec<usize>,
}

impl IcWire {
    pub fn new(name: IdString) -> IcWire {
        IcWire {
            name: name,
            pips_uphill: Vec::new(),
            pips_downhill: Vec::new(),
        }
    }
}

pub struct IcPip {
    name: IdString,
    from_wire: usize,
    to_wire: usize,
}

// A tile instance
struct IcTileInst {
    x: u32,
    y: u32,
    type_idx: usize,
    // mapping between wires and nodes
    wire_to_node: Vec<usize>,
}

impl IcTileInst {
    pub fn new(x: u32, y: u32) -> IcTileInst {
        IcTileInst {
            x: x,
            y: y,
            type_idx: 0,
            wire_to_node: Vec::new(),
        }
    }
}

// A reference to a tile wire
pub struct IcWireRef {
    tile_idx: usize,
    wire_idx: usize,
}

// A node instance
struct IcNode {
    // list of tile wires in the node
    wires: Vec<IcWireRef>,
}

impl IcNode {
    pub fn new() -> IcNode {
        IcNode {
            wires: Vec::new(),
        }
    }
}

// The overall routing resource graph
pub struct IcGraph {
    tile_types: IndexedMap<TileTypeKey, IcTileType>,
    tiles: Vec<IcTileInst>,
    nodes: Vec<IcNode>,
    width: u32,
    height: u32,
}

impl IcGraph {
    pub fn new(width: u32, height: u32) -> IcGraph {
        IcGraph {
            tile_types: IndexedMap::new(),
            tiles: (0..width).zip(0..height).map(|(x, y)| IcTileInst::new(x, y)).collect(),
            nodes: Vec::new(),
            width: width,
            height: height
        }
    }
}

pub struct GraphBuilder<'a> {
    g: IcGraph,
    ids: &'a mut IdStringDB,
    chip: &'a Chip,
    db: &'a mut Database,
    tiletypes_by_xy: HashMap<(u32, u32), TileTypeKey>,
    orig_tts: TileTypes,
}

impl <'a> GraphBuilder<'a> {
    fn new(ids: &'a mut IdStringDB, chip: &'a Chip, db: &'a mut Database) -> GraphBuilder<'a> {
        let mut width = 0;
        let mut height = 0;
        let mut tiletypes_by_xy = HashMap::new();
        for t in chip.tiles.iter() {
            tiletypes_by_xy.entry((t.x, t.y)).or_insert(TileTypeKey::new()).tile_types.push(t.tiletype.to_string());
            width = std::cmp::max(width, t.x + 1);
            height = std::cmp::max(height, t.y + 1);
        }

        let orig_tts = TileTypes::new(db, ids, &chip.family, &[&chip.device]);

        GraphBuilder {
            g: IcGraph::new(width, height),
            ids: ids,
            chip: chip,
            db: db,
            tiletypes_by_xy: tiletypes_by_xy,
            // the original tiletypes from the database
            orig_tts: orig_tts,
        }
    }
    fn setup_tiletypes(&mut self) {
        for t in self.g.tiles.iter_mut() {
            let key = self.tiletypes_by_xy.get(&(t.x, t.y)).unwrap();
            t.type_idx = self.g.tile_types.add(key, IcTileType::new(key.clone()));
        }
        for (key, lt) in self.g.tile_types.iter_mut() {
            // setup wires for all sub-tile-types
            for tt in key.tile_types.iter() {
                let tt_data = self.orig_tts.get(tt).unwrap();
                for wire in tt_data.wire_ids.iter() {
                    lt.wire(*wire);
                }
            }

        }
    }

    pub fn run(ids: &'a mut IdStringDB, chip: &'a Chip, db: &'a mut Database) -> IcGraph {
        let mut builder = GraphBuilder::new(ids, chip, db);
        builder.setup_tiletypes();
        builder.g
    }
}
<commit_msg>interchange: Create flattened node list<commit_after>use crate::chip::Chip;
use crate::database::Database;
use std::collections::{HashSet, HashMap};

use crate::bba::idstring::*;
use crate::bba::idxset::*;
use crate::bba::tiletype::{Neighbour, TileTypes};

// A tile type from the interchange format perspective
// this is not the same as a database tile type; because the Oxide graph can have
// more than one tile at a grid location whereas the interchange grid is one tile
// per location

#[derive(Clone, Eq, PartialEq, Hash)]
pub struct TileTypeKey {
    pub tile_types: Vec<String>,
}
impl TileTypeKey {
    pub fn new() -> TileTypeKey {
        TileTypeKey { tile_types: Vec::new() }
    }
}

pub struct IcTileType {
    key: TileTypeKey,
    wires: IndexedMap<IdString, IcWire>,
    pips: Vec<IcPip>,
    // TODO: constants, sites, etc
}

impl IcTileType {
    pub fn new(key: TileTypeKey) -> IcTileType {
        IcTileType {
            key: key,
            wires: IndexedMap::new(),
            pips: Vec::new(),
        }
    }
    pub fn wire(&mut self, name: IdString) -> usize {
        self.wires.add(&name, IcWire::new(name))
    }
    pub fn add_pip(&mut self, src: IdString, dst: IdString) {
        let src_idx = self.wire(src);
        let dst_idx = self.wire(dst);
        self.pips.push(IcPip {
            src_wire: src_idx,
            dst_wire: dst_idx,
        });
    }
}

pub struct IcWire {
    name: IdString,
}

impl IcWire {
    pub fn new(name: IdString) -> IcWire {
        IcWire {
            name: name,
        }
    }
}

pub struct IcPip {
    src_wire: usize,
    dst_wire: usize,
}

// A tile instance
pub struct IcTileInst {
    x: u32,
    y: u32,
    type_idx: usize,
    // mapping between wires and nodes
    wire_to_node: HashMap<usize, usize>,
}

impl IcTileInst {
    pub fn new(x: u32, y: u32) -> IcTileInst {
        IcTileInst {
            x: x,
            y: y,
            type_idx: 0,
            wire_to_node: HashMap::new(),
        }
    }
}

// A reference to a tile wire
#[derive(Clone, Hash, Eq, PartialEq)]
pub struct IcWireRef {
    tile_idx: usize,
    wire_idx: usize,
}

// A node instance
pub struct IcNode {
    // list of tile wires in the node
    wires: HashSet<IcWireRef>,
    root_wire: IcWireRef,
}

impl IcNode {
    pub fn new(root_wire: IcWireRef) -> IcNode {
        IcNode {
            wires: [root_wire.clone()].iter().cloned().collect(),
            root_wire: root_wire,
        }
    }
}

// The overall routing resource graph
pub struct IcGraph {
    tile_types: IndexedMap<TileTypeKey, IcTileType>,
    tiles: Vec<IcTileInst>,
    nodes: Vec<IcNode>,
    width: u32,
    height: u32,
}

impl IcGraph {
    pub fn new(width: u32, height: u32) -> IcGraph {
        IcGraph {
            tile_types: IndexedMap::new(),
            tiles: (0..width*height).map(|i| IcTileInst::new(i%width, i/width)).collect(),
            nodes: Vec::new(),
            width: width,
            height: height
        }
    }
    pub fn tile_idx(&self, x: u32, y: u32) -> usize {
        assert!(x < self.width);
        assert!(y < self.height);
        ((y * self.width) + x) as usize
    }
    pub fn tile_at(&mut self, x: u32, y: u32) -> &mut IcTileInst {
        let idx = self.tile_idx(x, y);
        &mut self.tiles[idx]
    }
    pub fn type_at(&mut self, x: u32, y: u32) -> &mut IcTileType {
        let idx = self.tile_at(x, y).type_idx;
        self.tile_types.value_mut(idx)
    }
    pub fn map_node(&mut self, root_x: u32, root_y: u32, root_wire: IdString, wire_x: u32, wire_y: u32, wire: IdString) {
        let root_idx = self.type_at(root_x, root_y).wire(root_wire);
        let wire_idx = self.type_at(wire_x, wire_y).wire(wire);
        let root_tile_idx = self.tile_idx(root_x, root_y);
        let node_idx = match self.tiles[root_tile_idx].wire_to_node.get(&root_idx) {
            Some(i) => *i,
            None => {
                let idx = self.nodes.len();
                self.nodes.push(IcNode::new(IcWireRef { tile_idx: root_tile_idx, wire_idx: root_idx }));
                self.tiles[root_tile_idx].wire_to_node.insert(root_idx, idx);
                idx
            }
        };
        let wire_tile_idx = self.tile_idx(wire_x, wire_y);
        self.nodes[node_idx].wires.insert(IcWireRef {tile_idx: wire_tile_idx, wire_idx: wire_idx });
    }
}

pub struct GraphBuilder<'a> {
    g: IcGraph,
    ids: &'a mut IdStringDB,
    chip: &'a Chip,
    db: &'a mut Database,
    tiletypes_by_xy: HashMap<(u32, u32), TileTypeKey>,
    orig_tts: TileTypes,
}

impl <'a> GraphBuilder<'a> {
    fn new(ids: &'a mut IdStringDB, chip: &'a Chip, db: &'a mut Database) -> GraphBuilder<'a> {
        let mut width = 0;
        let mut height = 0;
        let mut tiletypes_by_xy = HashMap::new();
        for t in chip.tiles.iter() {
            tiletypes_by_xy.entry((t.x, t.y)).or_insert(TileTypeKey::new()).tile_types.push(t.tiletype.to_string());
            width = std::cmp::max(width, t.x + 1);
            height = std::cmp::max(height, t.y + 1);
        }

        let orig_tts = TileTypes::new(db, ids, &chip.family, &[&chip.device]);

        GraphBuilder {
            g: IcGraph::new(width, height),
            ids: ids,
            chip: chip,
            db: db,
            tiletypes_by_xy: tiletypes_by_xy,
            // the original tiletypes from the database
            orig_tts: orig_tts,
        }
    }
    fn setup_tiletypes(&mut self) {
        for t in self.g.tiles.iter_mut() {
            let key = self.tiletypes_by_xy.get(&(t.x, t.y)).unwrap();
            t.type_idx = self.g.tile_types.add(key, IcTileType::new(key.clone()));
        }
        for (key, lt) in self.g.tile_types.iter_mut() {
            for tt in key.tile_types.iter() {
                // setup wires for all sub-tile-types
                let tt_data = self.orig_tts.get(tt).unwrap();
                for wire in tt_data.wire_ids.iter() {
                    lt.wire(*wire);
                }
                // setup pips, both fixed and not
                // TODO: skip site wires and pips and deal with these later
                let tdb = &self.db.tile_bitdb(&self.chip.family, tt).db;
                for (to_wire, pips) in tdb.pips.iter() {
                    for pip in pips.iter() {
                        lt.add_pip(self.ids.id(&pip.from_wire), self.ids.id(to_wire));
                    }
                }
                for (to_wire, conns) in tdb.conns.iter() {
                    for conn in conns.iter() {
                        lt.add_pip(self.ids.id(&conn.from_wire), self.ids.id(to_wire));
                    }
                }
            }
        }
    }
    // Convert a neighbour to a coordinate
    pub fn neighbour_tile(&self, x: u32, y: u32, n: &Neighbour) -> Option<(u32, u32)> {
        match n {
            Neighbour::RelXY { rel_x, rel_y } => {
                let nx = (x as i32) + rel_x;
                let ny = (y as i32) + rel_y;
                if nx >= 0 && ny >= 0 && (nx as u32) < self.g.width && (ny as u32) < self.g.height {
                    Some((nx as u32, ny as u32))
                } else {
                    None
                }
            }
            // TODO: globals
            _ => None
        }
    }
    fn setup_wire2node(&mut self) {
        for ((x, y), key) in self.tiletypes_by_xy.iter() {
            for tt in key.tile_types.iter() {
                for wire in self.orig_tts.get(tt).unwrap().wires.iter() {
                    let (neigh, base_wire) = Neighbour::parse_wire(wire);
                    if let Some(neigh) = neigh {
                        // it's a neighbour wire, map to the base tile
                        if let Some((root_x, root_y)) = self.neighbour_tile(*x, *y, &neigh) {
                            self.g.map_node(root_x, root_y, self.ids.id(base_wire), *x, *y, self.ids.id(wire));
                        }

                    } else {
                        // root node, map to itself
                        self.g.map_node(*x, *y, self.ids.id(base_wire), *x, *y, self.ids.id(base_wire));
                    }
                }
            }
        }
    }

    pub fn run(ids: &'a mut IdStringDB, chip: &'a Chip, db: &'a mut Database) -> IcGraph {
        let mut builder = GraphBuilder::new(ids, chip, db);
        builder.setup_tiletypes();
        builder.setup_wire2node();
        builder.g
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use std::marker::PhantomData;

// What does this do? You'll never guess!
type HeapId<'a> = PhantomData<std::cell::Cell<&'a mut ()>>;

// The heap is (for now) just a big Vec of Pairs
pub struct Heap<'a> {
    id: HeapId<'a>,
    storage: Vec<Pair<'a>>,
    freelist: *mut Pair<'a>,
    pins: RefCell<HashMap<*mut Pair<'a>, usize>>
}

pub const HEAP_SIZE: usize = 10000;

pub fn with_heap<F, O>(f: F) -> O
    where F: for<'a> FnOnce(&mut Heap<'a>) -> O
{
    f(&mut Heap::new())
}

impl<'a> Heap<'a> {
    fn new() -> Heap<'a> {
        // Allocate with the full capacity so that allocated Pairs never move
        let mut h = Heap {
            id: PhantomData,
            storage: Vec::with_capacity(HEAP_SIZE),
            freelist: std::ptr::null_mut(),
            pins: RefCell::new(HashMap::new())
        };
        for i in 0 .. HEAP_SIZE {
            h.storage.push(Pair {
                mark: false,
                head: XValue::Null,
                tail: XValue::Null
            });
            let p = &mut h.storage[i] as *mut Pair<'a>;
            unsafe {
                h.add_to_free_list(p);
            }
        }
        h
    }

    fn pin(&self, p: *mut Pair<'a>) {
        let mut pins = self.pins.borrow_mut();
        let entry = pins.entry(p).or_insert(0);
        *entry += 1;
    }

    fn unpin(&self, p: *mut Pair<'a>) {
        let mut pins = self.pins.borrow_mut();
        if {
            let entry = pins.entry(p).or_insert(0);
            assert!(*entry != 0);
            *entry -= 1;
            *entry == 0
        } {
            pins.remove(&p);
        }
    }

    unsafe fn add_to_free_list(&mut self, p: *mut Pair<'a>) {
        let listp: *mut *mut Pair<'a> = std::mem::transmute(p);
        *listp = self.freelist;
        assert_eq!(*listp, self.freelist);
        self.freelist = p;
    }

    pub fn try_alloc(&mut self, pair: (Value<'a>, Value<'a>)) -> Option<PairRoot<'a>> {
        if self.freelist.is_null() {
            unsafe {
                self.gc();
            }
            if self.freelist.is_null() {
                return None;
            }
        }

        let p = self.freelist;
        unsafe {
            let listp: *mut *mut Pair<'a> = std::mem::transmute(p);
            self.freelist = *listp;

            let (h, t) = pair;
            *p = Pair {
                mark: false,
                head: value_to_heap(h),
                tail: value_to_heap(t)
            };
            Some(PairRoot::new(self, p))
        }
    }

    pub fn alloc(&mut self, pair: (Value<'a>, Value<'a>)) -> PairRoot<'a> {
        self.try_alloc(pair).expect("out of memory (gc did not collect anything)")
    }

    pub fn alloc_null(&mut self) -> PairRoot<'a> {
        self.alloc((Value::Null, Value::Null))
    }

    unsafe fn mark(p: *mut Pair<'a>) {
        if !p.is_null() && !(*p).mark {
            (*p).mark = true;
            Heap::mark_value(&(*p).head);
            Heap::mark_value(&(*p).tail);
        }
    }

    unsafe fn mark_value(v: &XValue<'a>) {
        match v {
            &XValue::Pair(p, _) => Heap::mark(p),
            _ => {}
        }
    }

    unsafe fn gc(&mut self) {
        // clear mark bits
        for p in &mut self.storage {
            p.mark = false;
        }

        // mark phase
        for (&p, _) in self.pins.borrow().iter() {
            Heap::mark(p);
        }

        // sweep phase
        self.freelist = std::ptr::null_mut();
        for i in 0 .. HEAP_SIZE {
            let p = &mut self.storage[i] as *mut Pair<'a>;
            if !(*p).mark {
                self.add_to_free_list(p);
            }
        }
    }

    #[cfg(test)]
    pub fn force_gc(&mut self) {
        unsafe { self.gc(); }
    }
}

// === Pair, the reference type

// Pair is the only type that is actually allocated inside the heap (private)
struct Pair<'a> {
    mark: bool,
    head: XValue<'a>,
    tail: XValue<'a>
}

// Handle to a Pair that lives in the heap.
#[allow(raw_pointer_derive)]
#[derive(Debug, PartialEq)]
pub struct PairRoot<'a> {
    ptr: *mut Pair<'a>,
    heap: *const Heap<'a>,
    heap_id: HeapId<'a>
}

impl<'a> Drop for PairRoot<'a> {
    fn drop(&mut self) {
        unsafe {
            (*self.heap).unpin(self.ptr);
        }
    }
}

impl<'a> Clone for PairRoot<'a> {
    fn clone(&self) -> PairRoot<'a> {
        let &PairRoot { ptr, heap, heap_id } = self;
        unsafe {
            (*heap).pin(ptr);
        }
        PairRoot {
            ptr: ptr,
            heap: heap,
            heap_id: heap_id
        }
    }
}

impl<'a> PairRoot<'a> {
    unsafe fn new(heap: &Heap<'a>, p: *mut Pair<'a>) -> PairRoot<'a> {
        heap.pin(p);
        PairRoot {
            ptr: p,
            heap: heap as *const Heap<'a>,
            heap_id: heap.id
        }
    }

    pub fn head(&self) -> Value<'a> {
        let ptr = self.ptr;
        unsafe { value_from_heap(&*self.heap, &(*ptr).head) }
    }

    pub fn tail(&self) -> Value<'a> {
        let ptr = self.ptr;
        unsafe { value_from_heap(&*self.heap, &(*ptr).tail) }
    }

    pub fn set_head(&self, v: Value<'a>) {
        let ptr = self.ptr;
        unsafe { (*ptr).head = value_to_heap(v); }
    }

    pub fn set_tail(&self, v: Value<'a>) {
        let ptr = self.ptr;
        unsafe { (*ptr).tail = value_to_heap(v); }
    }

    #[cfg(test)]
    pub fn address(&self) -> usize {
        unsafe { std::mem::transmute(self.ptr) }
    }
}

// === Values (a heap-inline enum)

// Values inside the heap (GC heap-to-heap cross-references) (private)
enum XValue<'a> {
    Null,
    Int(i32),
    Str(Rc<String>),
    Pair(*mut Pair<'a>, HeapId<'a>)
}

#[derive(Debug, Clone, PartialEq)]
pub enum Value<'a> {
    Null,
    Int(i32),
    Str(Rc<String>),  // <-- equality is by value
    Pair(PairRoot<'a>)  // <-- equality is by pointer
}

// === Getting data into and out of the heap

fn value_to_heap<'a>(v: Value<'a>) -> XValue<'a> {
    match v {
        Value::Null => XValue::Null,
        Value::Int(n) => XValue::Int(n),
        Value::Str(rcstr) => XValue::Str(rcstr),
        Value::Pair(PairRoot{ptr, heap_id, ..}) => XValue::Pair(ptr, heap_id)
    }
}

unsafe fn value_from_heap<'a>(heap: &Heap<'a>, v: &XValue<'a>) -> Value<'a> {
    match v {
        &XValue::Null => Value::Null,
        &XValue::Int(n) => Value::Int(n),
        &XValue::Str(ref rcstr) => Value::Str(rcstr.clone()),
        &XValue::Pair(ptr, _) => Value::Pair(PairRoot::new(heap, ptr))
    }
}

#[cfg(test)]
mod test;
<commit_msg>Introduce `trait Mark`.<commit_after>use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use std::marker::PhantomData;

// What does this do? You'll never guess!
type HeapId<'a> = PhantomData<std::cell::Cell<&'a mut ()>>;

// The heap is (for now) just a big Vec of Pairs
pub struct Heap<'a> {
    id: HeapId<'a>,
    storage: Vec<Pair<'a>>,
    freelist: *mut Pair<'a>,
    pins: RefCell<HashMap<*mut Pair<'a>, usize>>
}

pub const HEAP_SIZE: usize = 10000;

pub fn with_heap<F, O>(f: F) -> O
    where F: for<'a> FnOnce(&mut Heap<'a>) -> O
{
    f(&mut Heap::new())
}

unsafe trait Mark {
    unsafe fn mark(ptr: *mut Self);
}

impl<'a> Heap<'a> {
    fn new() -> Heap<'a> {
        // Allocate with the full capacity so that allocated Pairs never move
        let mut h = Heap {
            id: PhantomData,
            storage: Vec::with_capacity(HEAP_SIZE),
            freelist: std::ptr::null_mut(),
            pins: RefCell::new(HashMap::new())
        };
        for i in 0 .. HEAP_SIZE {
            h.storage.push(Pair {
                marked: false,
                head: XValue::Null,
                tail: XValue::Null
            });
            let p = &mut h.storage[i] as *mut Pair<'a>;
            unsafe {
                h.add_to_free_list(p);
            }
        }
        h
    }

    fn pin(&self, p: *mut Pair<'a>) {
        let mut pins = self.pins.borrow_mut();
        let entry = pins.entry(p).or_insert(0);
        *entry += 1;
    }

    fn unpin(&self, p: *mut Pair<'a>) {
        let mut pins = self.pins.borrow_mut();
        if {
            let entry = pins.entry(p).or_insert(0);
            assert!(*entry != 0);
            *entry -= 1;
            *entry == 0
        } {
            pins.remove(&p);
        }
    }

    unsafe fn add_to_free_list(&mut self, p: *mut Pair<'a>) {
        let listp: *mut *mut Pair<'a> = std::mem::transmute(p);
        *listp = self.freelist;
        assert_eq!(*listp, self.freelist);
        self.freelist = p;
    }

    pub fn try_alloc(&mut self, pair: (Value<'a>, Value<'a>)) -> Option<PairRoot<'a>> {
        if self.freelist.is_null() {
            unsafe {
                self.gc();
            }
            if self.freelist.is_null() {
                return None;
            }
        }

        let p = self.freelist;
        unsafe {
            let listp: *mut *mut Pair<'a> = std::mem::transmute(p);
            self.freelist = *listp;

            let (h, t) = pair;
            *p = Pair {
                marked: false,
                head: value_to_heap(h),
                tail: value_to_heap(t)
            };
            Some(PairRoot::new(self, p))
        }
    }

    pub fn alloc(&mut self, pair: (Value<'a>, Value<'a>)) -> PairRoot<'a> {
        self.try_alloc(pair).expect("out of memory (gc did not collect anything)")
    }

    pub fn alloc_null(&mut self) -> PairRoot<'a> {
        self.alloc((Value::Null, Value::Null))
    }

    unsafe fn gc(&mut self) {
        // clear mark bits
        for p in &mut self.storage {
            p.marked = false;
        }

        // mark phase
        for (&p, _) in self.pins.borrow().iter() {
            Mark::mark(p);
        }

        // sweep phase
        self.freelist = std::ptr::null_mut();
        for i in 0 .. HEAP_SIZE {
            let p = &mut self.storage[i] as *mut Pair<'a>;
            if !(*p).marked {
                self.add_to_free_list(p);
            }
        }
    }

    #[cfg(test)]
    pub fn force_gc(&mut self) {
        unsafe { self.gc(); }
    }
}

// === Pair, the reference type

// Pair is the only type that is actually allocated inside the heap (private)
struct Pair<'a> {
    marked: bool,
    head: XValue<'a>,
    tail: XValue<'a>
}

unsafe impl<'a> Mark for Pair<'a> {
    unsafe fn mark(ptr: *mut Pair<'a>) {
        if !ptr.is_null() && !(*ptr).marked {
            (*ptr).marked = true;
            Mark::mark(&mut (*ptr).head as *mut XValue<'a>);
            Mark::mark(&mut (*ptr).tail as *mut XValue<'a>);
        }
    }
}

// Handle to a Pair that lives in the heap.
#[allow(raw_pointer_derive)]
#[derive(Debug, PartialEq)]
pub struct PairRoot<'a> {
    ptr: *mut Pair<'a>,
    heap: *const Heap<'a>,
    heap_id: HeapId<'a>
}

impl<'a> Drop for PairRoot<'a> {
    fn drop(&mut self) {
        unsafe {
            (*self.heap).unpin(self.ptr);
        }
    }
}

impl<'a> Clone for PairRoot<'a> {
    fn clone(&self) -> PairRoot<'a> {
        let &PairRoot { ptr, heap, heap_id } = self;
        unsafe {
            (*heap).pin(ptr);
        }
        PairRoot {
            ptr: ptr,
            heap: heap,
            heap_id: heap_id
        }
    }
}

impl<'a> PairRoot<'a> {
    unsafe fn new(heap: &Heap<'a>, p: *mut Pair<'a>) -> PairRoot<'a> {
        heap.pin(p);
        PairRoot {
            ptr: p,
            heap: heap as *const Heap<'a>,
            heap_id: heap.id
        }
    }

    pub fn head(&self) -> Value<'a> {
        let ptr = self.ptr;
        unsafe { value_from_heap(&*self.heap, &(*ptr).head) }
    }

    pub fn tail(&self) -> Value<'a> {
        let ptr = self.ptr;
        unsafe { value_from_heap(&*self.heap, &(*ptr).tail) }
    }

    pub fn set_head(&self, v: Value<'a>) {
        let ptr = self.ptr;
        unsafe { (*ptr).head = value_to_heap(v); }
    }

    pub fn set_tail(&self, v: Value<'a>) {
        let ptr = self.ptr;
        unsafe { (*ptr).tail = value_to_heap(v); }
    }

    #[cfg(test)]
    pub fn address(&self) -> usize {
        unsafe { std::mem::transmute(self.ptr) }
    }
}

// === Values (a heap-inline enum)

// Values inside the heap (GC heap-to-heap cross-references) (private)
enum XValue<'a> {
    Null,
    Int(i32),
    Str(Rc<String>),
    Pair(*mut Pair<'a>, HeapId<'a>)
}

unsafe impl<'a> Mark for XValue<'a> {
    unsafe fn mark(ptr: *mut XValue<'a>) {
        match *ptr {
            XValue::Pair(p, _) => Mark::mark(p),
            _ => {}
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum Value<'a> {
    Null,
    Int(i32),
    Str(Rc<String>),  // <-- equality is by value
    Pair(PairRoot<'a>)  // <-- equality is by pointer
}

// === Getting data into and out of the heap

fn value_to_heap<'a>(v: Value<'a>) -> XValue<'a> {
    match v {
        Value::Null => XValue::Null,
        Value::Int(n) => XValue::Int(n),
        Value::Str(rcstr) => XValue::Str(rcstr),
        Value::Pair(PairRoot{ptr, heap_id, ..}) => XValue::Pair(ptr, heap_id)
    }
}

unsafe fn value_from_heap<'a>(heap: &Heap<'a>, v: &XValue<'a>) -> Value<'a> {
    match v {
        &XValue::Null => Value::Null,
        &XValue::Int(n) => Value::Int(n),
        &XValue::Str(ref rcstr) => Value::Str(rcstr.clone()),
        &XValue::Pair(ptr, _) => Value::Pair(PairRoot::new(heap, ptr))
    }
}

#[cfg(test)]
mod test;
<|endoftext|>


<commit_before>//! Use the API Documentation below to learn about the various things you can do with this crate.
//!
//! **If this is your first time using Rust or using this crate, read the Guide on
//! [turtle.rs](http://turtle.rs) to learn how to start.**
//!
//! * The [`Turtle` struct](struct.Turtle.html) - lists of all the various drawing commands that the
//!   turtle supports
//! * The [`Drawing` struct](struct.Drawing.html) - allows you to manipulate the title, size,
//!   background and more of the drawing that you are creating
//! * The [`color` module](color/index.html) - describes the different ways to create colors and
//!   includes a list of the hundreds of predefined color names that you can use to easily set the
//!   pen, fill, and background color of your drawings
//!
//! Note: Call [`turtle::start()`](fn.start.html) if you do not create a turtle with
//! [`Turtle::new()`](struct.Turtle.html#method.new) right at the beginning of your program. Most
//! programs will never need to call this function as it is called for you in
//! [`Turtle::new()`](struct.Turtle.html#method.new).
//!
//! # Random Values
//!
//! See the [`rand` module](rand/index.html) for information about generating random colors, speeds,
//! angles, and more which can be used in your programs to produce some interesting results!
//!
//! # Event Handling
//!
//! The [`Event` enum](event/enum.Event.html) documentation provides information about how you can
//! create an event loop. This allows you to draw things in response to certain events like the
//! mouse moving, keys being pressed, and more.
//!
//! The `Turtle` struct contains a few convenience methods so you can do some common event-related
//! things without creating the entire event loop. For example, use
//! [`wait_for_click()`](struct.Turtle.html#method.wait_for_click) to wait for the user to click
//! anywhere on the screen before proceeding.
//! # Unstable features
//!
//! Some parts of this crate are unstable and may be subject to change in the future. If you would
//! like to use unstable functionality, enable the "unstable" feature in your `Cargo.toml` file as
//! shown below:
//!
//! ```toml
//! [dependencies]
//! # Explicitly opt-in to unstable features that may change in the future
//! turtle = { version = "...", features = ["unstable"] }
//! ```
//!
//! If you are developing this crate with a local version of the turtle repository, see the
//! [CONTRIBUTING.md] file for the specific commands you should run to generate the documentation.
//!
//! [CONTRIBUTING.md]: https://github.com/sunjay/turtle/blob/master/CONTRIBUTING.md

// This warning usually signals an error and so it should be treated as such.
#![deny(unused_must_use)]

#![doc(html_logo_url = "https://raw.githubusercontent.com/sunjay/turtle/master/docs/assets/images/turtle-logo-512.png")]
#![cfg_attr(docsrs, feature(doc_cfg))]

#[cfg(all(test, not(feature = "test")))]
compile_error!("Make sure you run tests with `cargo test --features test`");

mod radians;
mod point;
mod speed;
pub mod color;
pub mod rand;

mod ipc_protocol;
mod renderer_server_process;
mod renderer_server;
mod renderer_client;
mod async_drawing;
mod async_turtle;
mod sync_runtime;
mod drawing;
mod turtle;

pub use crate::color::Color;
pub use crate::async_drawing::Size;
pub use crate::drawing::Drawing;
pub use crate::point::Point;
pub use crate::speed::Speed;
pub use crate::async_turtle::{Angle, Distance};
pub use crate::turtle::Turtle;
pub use crate::renderer_server::ExportError;

#[cfg(feature = "unstable")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
pub mod event;
#[cfg(feature = "unstable")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
pub use crate::event::Event;
#[cfg(not(feature = "unstable"))]
mod event;
#[cfg(not(feature = "unstable"))]
use crate::event::Event;

#[cfg(not(any(feature = "test", test)))]
pub use crate::renderer_server::start;
#[cfg(any(feature = "test", test))]
pub fn start() {}
<commit_msg>Conditional documentation for pointing out that docs need to be built with --features "unstable" or some links may be broken<commit_after>//! Use the API Documentation below to learn about the various things you can do with this crate.
//!
//! **If this is your first time using Rust or using this crate, read the Guide on
//! [turtle.rs](http://turtle.rs) to learn how to start.**
//!
//! * The [`Turtle` struct](struct.Turtle.html) - lists of all the various drawing commands that the
//!   turtle supports
//! * The [`Drawing` struct](struct.Drawing.html) - allows you to manipulate the title, size,
//!   background and more of the drawing that you are creating
//! * The [`color` module](color/index.html) - describes the different ways to create colors and
//!   includes a list of the hundreds of predefined color names that you can use to easily set the
//!   pen, fill, and background color of your drawings
//!
//! Note: Call [`turtle::start()`](fn.start.html) if you do not create a turtle with
//! [`Turtle::new()`](struct.Turtle.html#method.new) right at the beginning of your program. Most
//! programs will never need to call this function as it is called for you in
//! [`Turtle::new()`](struct.Turtle.html#method.new).
//!
//! # Random Values
//!
//! See the [`rand` module](rand/index.html) for information about generating random colors, speeds,
//! angles, and more which can be used in your programs to produce some interesting results!
//!
//! # Event Handling
//!
#![cfg_attr(not(feature = "unstable"), doc = "
**The turtle events API is unstable.** Rebuild the documentation with `--features \"unstable\"` to
show the documentation for the types and modules that are part of that. Some links may appear
broken unless you do so. See [Unstable features](#unstable-features) below for more information.
")]
//! The [`Event` enum](event/enum.Event.html) documentation provides information about how you can
//! create an event loop. This allows you to draw things in response to certain events like the
//! mouse moving, keys being pressed, and more.
//!
//! The `Turtle` struct contains a few convenience methods so you can do some common event-related
//! things without creating the entire event loop. For example, use
//! [`wait_for_click()`](struct.Turtle.html#method.wait_for_click) to wait for the user to click
//! anywhere on the screen before proceeding.
//!
//! # Unstable features
//!
//! Some parts of this crate are unstable and may be subject to change in the future. If you would
//! like to use unstable functionality, enable the "unstable" feature in your `Cargo.toml` file as
//! shown below:
//!
//! ```toml
//! [dependencies]
//! # Explicitly opt-in to unstable features that may change in the future
//! turtle = { version = "...", features = ["unstable"] }
//! ```
//!
//! If you are developing this crate with a local version of the turtle repository, see the
//! [CONTRIBUTING.md] file for the specific commands you should run to generate the documentation.
//!
//! [CONTRIBUTING.md]: https://github.com/sunjay/turtle/blob/master/CONTRIBUTING.md

// This warning usually signals an error and so it should be treated as such.
#![deny(unused_must_use)]

#![doc(html_logo_url = "https://raw.githubusercontent.com/sunjay/turtle/master/docs/assets/images/turtle-logo-512.png")]
#![cfg_attr(docsrs, feature(doc_cfg))]

#[cfg(all(test, not(feature = "test")))]
compile_error!("Make sure you run tests with `cargo test --features test`");

mod radians;
mod point;
mod speed;
pub mod color;
pub mod rand;

mod ipc_protocol;
mod renderer_server_process;
mod renderer_server;
mod renderer_client;
mod async_drawing;
mod async_turtle;
mod sync_runtime;
mod drawing;
mod turtle;

pub use crate::color::Color;
pub use crate::async_drawing::Size;
pub use crate::drawing::Drawing;
pub use crate::point::Point;
pub use crate::speed::Speed;
pub use crate::async_turtle::{Angle, Distance};
pub use crate::turtle::Turtle;
pub use crate::renderer_server::ExportError;

#[cfg(feature = "unstable")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
pub mod event;
#[cfg(feature = "unstable")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
pub use crate::event::Event;
#[cfg(not(feature = "unstable"))]
mod event;
#[cfg(not(feature = "unstable"))]
use crate::event::Event;

#[cfg(not(any(feature = "test", test)))]
pub use crate::renderer_server::start;
#[cfg(any(feature = "test", test))]
pub fn start() {}
<|endoftext|>


<commit_before>#![license = "MIT"]
#![deny(missing_docs)]
#![feature(unsafe_destructor)]

//! A library for setting current values for stack scope,
//! such as application structure.

pub use current::{ Current, CurrentGuard };

mod current;

/// Allows use of the implemented type as an argument to Set::set.
///
/// This allows types to be used for ad-hoc overloading of Set::set
/// to perform complex updates to the parameter of Modifier.
pub trait Modifier<F> {
    /// Modify `F` with self.
    fn modify(self, &mut F);
}

/// A blanket trait providing the set and set_mut methods for all types.
pub trait Set<M: Modifier<Self>> {
    /// Modify self using the provided modifier.
    #[inline(always)]
    fn set(mut self, modifier: M) -> Self {
        modifier.modify(&mut self);
        self
    }

    /// Modify self through a mutable reference with the provided modifier.
    ///
    /// Note that this still causes a shallow copy of self, so can be
    /// slow for types which are expensive to move.
    #[inline(always)]
    fn set_mut(&mut self, modifier: M) -> &mut Self {
        modifier.modify(self);
        self
    }
}

impl<T, U: Modifier<T>> Set<U> for T {}

/// Implemented by types that can be constructed from another value.
pub trait Get<T> {
    /// Returns new value.
    fn get(&self) -> T;
}

/// Transmutes the current value to a lifetime scope.
/// The scope must not outlive the guard.
/// This is used to work around issues with closure that require move by value.
pub unsafe fn unsafe_current_unwrap<T>(_scope: &()) -> &T {
    Current::with_current_unwrap(|current: &T| {
        use std::mem::transmute;
        transmute(current)
    })
}

/// Sets value on current type, assuming using a `RefCell` to make it safe.
/// Panics if there is no current object of type `T`.
pub fn set<T, U: Modifier<T>>(val: U) {
    use std::cell::RefCell;
    let scope = &();
    let current: &RefCell<T> = unsafe { unsafe_current_unwrap(scope) };
    val.modify(&mut*current.borrow_mut());
}

/// Gets value from current object of type `T`.
/// The returned type must implement the `GetFrom` trait.
pub fn get<T: Get<U>, U>() -> U {
    use std::cell::RefCell;
    Current::with_current_unwrap(|current: &RefCell<T>| {
        match current.try_borrow() {
            Some(val) => val.get(),
            None => {
                use std::intrinsics::get_tydesc;
                let name = unsafe { (*get_tydesc::<T>()).name };
                panic!("The current `{}` is already in use", name);
            }
        }
    })
}
<commit_msg>Removed part of comment on `set_mut`<commit_after>#![license = "MIT"]
#![deny(missing_docs)]
#![feature(unsafe_destructor)]

//! A library for setting current values for stack scope,
//! such as application structure.

pub use current::{ Current, CurrentGuard };

mod current;

/// Allows use of the implemented type as an argument to Set::set.
///
/// This allows types to be used for ad-hoc overloading of Set::set
/// to perform complex updates to the parameter of Modifier.
pub trait Modifier<F> {
    /// Modify `F` with self.
    fn modify(self, &mut F);
}

/// A blanket trait providing the set and set_mut methods for all types.
pub trait Set<M: Modifier<Self>> {
    /// Modify self using the provided modifier.
    #[inline(always)]
    fn set(mut self, modifier: M) -> Self {
        modifier.modify(&mut self);
        self
    }

    /// Modify self through a mutable reference with the provided modifier.
    #[inline(always)]
    fn set_mut(&mut self, modifier: M) -> &mut Self {
        modifier.modify(self);
        self
    }
}

impl<T, U: Modifier<T>> Set<U> for T {}

/// Implemented by types that can be constructed from another value.
pub trait Get<T> {
    /// Returns new value.
    fn get(&self) -> T;
}

/// Transmutes the current value to a lifetime scope.
/// The scope must not outlive the guard.
/// This is used to work around issues with closure that require move by value.
pub unsafe fn unsafe_current_unwrap<T>(_scope: &()) -> &T {
    Current::with_current_unwrap(|current: &T| {
        use std::mem::transmute;
        transmute(current)
    })
}

/// Sets value on current type, assuming using a `RefCell` to make it safe.
/// Panics if there is no current object of type `T`.
pub fn set<T, U: Modifier<T>>(val: U) {
    use std::cell::RefCell;
    let scope = &();
    let current: &RefCell<T> = unsafe { unsafe_current_unwrap(scope) };
    val.modify(&mut*current.borrow_mut());
}

/// Gets value from current object of type `T`.
/// The returned type must implement the `GetFrom` trait.
pub fn get<T: Get<U>, U>() -> U {
    use std::cell::RefCell;
    Current::with_current_unwrap(|current: &RefCell<T>| {
        match current.try_borrow() {
            Some(val) => val.get(),
            None => {
                use std::intrinsics::get_tydesc;
                let name = unsafe { (*get_tydesc::<T>()).name };
                panic!("The current `{}` is already in use", name);
            }
        }
    })
}
<|endoftext|>


<commit_before>//! My personal website.

#![feature(associated_consts)]
#![feature(custom_derive)]
#![feature(plugin)]

#![plugin(dotenv_macros)]
#![plugin(serde_macros)]

#![warn(missing_docs)]

#[macro_use]
extern crate maplit;
#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate regex;
#[macro_use]
extern crate router;
#[macro_use]
extern crate quick_error;

extern crate ammonia;
extern crate chrono;
extern crate dotenv;
extern crate handlebars;
extern crate handlebars_iron as hbs;
extern crate hoedown;
extern crate hyper;
extern crate iron;
extern crate mount;
extern crate persistent;
extern crate rustc_serialize;
extern crate rusqlite;
extern crate serde;
extern crate serde_json;
extern crate staticfile;
extern crate toml;
extern crate url;
extern crate serde_yaml;

pub mod blog;
pub mod config;
pub mod helpers;
pub mod markdown;
pub mod persistence;
pub mod projects;
pub mod routes;

use std::env;
use std::fs::File;
use std::error::Error;
use std::io::prelude::*;
use std::net::ToSocketAddrs;

use iron::prelude::*;

/// Starts the server listening on the provided socket address.
pub fn listen<A>(addr: A)
    where A: ToSocketAddrs
{
    let config_path = env::var("WEBSITE_CONFIG").unwrap_or_else(|_| String::from("config.yaml"));
    let config = config::load(config_path).expect("could not parse configuration");
    let projects = projects::load("projects.yaml").expect("problem parsing projects");

    // Insert blog posts into the database.
    let connection = persistence::get_db_connection();
    let schema = {
        let mut schema_file = File::open("schema.sql").unwrap();
        let mut schema = String::new();
        schema_file.read_to_string(&mut schema).unwrap();
        schema
    };

    connection.execute_batch(&schema).unwrap();

    blog::load("blog/", &connection).expect("problem parsing blog posts");

    let handler = routes::handler(config, projects);

    Iron::new(handler)
        .http(addr)
        .unwrap_or_else(|e| {
            panic!("Error: {:?}", e.description());
        });
}
<commit_msg>feat(log): log additional server events<commit_after>//! My personal website.

#![feature(associated_consts)]
#![feature(custom_derive)]
#![feature(plugin)]

#![plugin(dotenv_macros)]
#![plugin(serde_macros)]

#![warn(missing_docs)]

#[macro_use]
extern crate maplit;
#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate regex;
#[macro_use]
extern crate router;
#[macro_use]
extern crate quick_error;

extern crate ammonia;
extern crate chrono;
extern crate dotenv;
extern crate handlebars;
extern crate handlebars_iron as hbs;
extern crate hoedown;
extern crate hyper;
extern crate iron;
extern crate mount;
extern crate persistent;
extern crate rustc_serialize;
extern crate rusqlite;
extern crate serde;
extern crate serde_json;
extern crate staticfile;
extern crate toml;
extern crate url;
extern crate serde_yaml;

pub mod blog;
pub mod config;
pub mod helpers;
pub mod markdown;
pub mod persistence;
pub mod projects;
pub mod routes;

use std::env;
use std::fs::File;
use std::error::Error;
use std::io::prelude::*;
use std::net::ToSocketAddrs;

use iron::prelude::*;

/// Starts the server listening on the provided socket address.
pub fn listen<A>(addr: A)
    where A: ToSocketAddrs
{
    let config_path = env::var("WEBSITE_CONFIG").unwrap_or_else(|_| String::from("config.yaml"));
    let config = config::load(config_path).expect("could not parse configuration");
    let projects = projects::load("projects.yaml").expect("problem parsing projects");

    // Insert blog posts into the database.
    let connection = persistence::get_db_connection();
    let schema = {
        let mut schema_file = File::open("schema.sql").unwrap();
        let mut schema = String::new();
        schema_file.read_to_string(&mut schema).unwrap();
        schema
    };

    connection.execute_batch(&schema).unwrap();

    blog::load("blog/", &connection).expect("problem parsing blog posts");

    let handler = routes::handler(config, projects);

    info!("initialization complete");

    let listening = Iron::new(handler)
        .http(addr)
        .unwrap_or_else(|e| {
            panic!("Error: {:?}", e.description());
        });

    info!("listening on {}", listening.socket);
}
<|endoftext|>


<commit_before>#![no_std]
#![feature(globs, phase, asm, macro_rules, lang_items, default_type_params, unboxed_closures)]

#[cfg(test)] #[phase(plugin, link)] extern crate log;

#[cfg(not(test))] extern crate "os_alloc" as alloc;
#[cfg(test)] extern crate alloc;
extern crate unicode;
#[phase(plugin, link)] extern crate core;
#[cfg(not(test))] extern crate "os_collections" as core_collections;
#[cfg(test)] extern crate "collections" as core_collections;
extern crate "rand" as core_rand;
extern crate rlibc;
extern crate spinlock;

// Make std testable by not duplicating lang items. See #2912
#[cfg(test)] extern crate "std" as realstd;
#[cfg(test)] pub use realstd::kinds;
#[cfg(test)] pub use realstd::ops;
#[cfg(test)] pub use realstd::cmp;
#[cfg(test)] pub use realstd::boxed;

// NB: These reexports are in the order they should be listed in rustdoc

pub use core::any;
pub use core::borrow;
pub use core::cell;
pub use core::clone;
#[cfg(not(test))] pub use core::cmp;
pub use core::default;
pub use core::finally;
pub use core::intrinsics;
pub use core::iter;
#[cfg(not(test))] pub use core::kinds;
pub use core::mem;
#[cfg(not(test))] pub use core::ops;
pub use core::ptr;
pub use core::raw;
pub use core::simd;
pub use core::result;
pub use core::option;

#[cfg(not(test))] pub use alloc::boxed;
pub use alloc::rc;

pub use core_collections::slice;
pub use core_collections::str;
pub use core_collections::string;
pub use core_collections::vec;

pub use unicode::char;

use core::prelude::*;

/* Exported macros */

pub mod macros;

/* new for os */
mod multiboot;
mod init;
mod vga_buffer;
mod fn_box;
mod scheduler;
mod global;

pub mod fmt;

/* Common data structures */

pub mod collections;

// Documentation for primitive types

mod bool;
mod unit;
mod tuple;

#[no_mangle]
pub fn main(multiboot: *const multiboot::Information) {

    unsafe{init::frame_stack(multiboot)};
    global::init();
    unsafe{enable_interrupts()};

    print!("test\n\niuaeiae");
    let x = box 5i;

    let y = 0xb8000 as *mut u64;
    unsafe{*y = 0xffffffffffffffff};

    print!("test");
    print!("test\n");
    println!("newline {}", x);

    loop{
        let mut x = 0u;
            for i in range(0,1000000) {
                x = i;
            }
        print!("m {} ", x);
    }
    scheduler::spawn(|| print!("I'm #1!\n"));
    scheduler::spawn(|| -> () {
        loop {
            print!("a");
            /*let mut x = 0u;
            for i in range(0,1000000) {
                x = i;
            }
            print!("a {}\n", x);*/
        }
    });

    scheduler::spawn(|| -> () {
        loop {
            print!("b");
            /*
            let mut x = 0u;
            for i in range(0,1000000) {
                x = i;
            }
            print!("b {}\n", x);
            */
        }
    });
    scheduler::spawn(|| -> () {
        loop {
            let mut x = 0u;
            for i in range(0,1000000) {
                x = i;
            }
            print!("c {}\n", x);
        }
    });
    scheduler::spawn(|| -> () {
        loop {
            let mut x = 0u;
            for i in range(0,1000000) {
                x = i;
            }
            print!("d {}\n", x);
        }
    });

    loop{}
    panic!("end of os!");
}

// A curious inner-module that's not exported that contains the binding
// 'std' so that macro-expanded references to std::error and such
// can be resolved within libstd.
#[doc(hidden)]
mod std {
    // mods used for deriving
    pub use clone;
    pub use cmp;
    //pub use hash;

    //pub use comm; // used for select!()
    //pub use error; // used for try!()
    pub use fmt; // used for any formatting strings
    //pub use io; // used for println!()
    pub use option; // used for bitflags!{}
    //pub use rt; // used for panic!()
    pub use vec; // used for vec![]
    pub use cell; // used for tls!
    //pub use thread_local; // used for thread_local!
    pub use kinds; // used for tls!

    // The test runner calls ::std::os::args() but really wants realstd
    #[cfg(test)] pub use realstd::os as os;
    // The test runner requires std::slice::Vector, so re-export std::slice just for it.
    //
    // It is also used in vec![]
    pub use slice;

    pub use boxed; // used for vec![]

}

/* Interrupt Handlers */

extern {
//    fn send_eoi(interrupt_number: u64) -> int; //return value to mark rax as used
}

unsafe fn out_byte(port: u16, data: u8) {
    asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(data) :: "volatile");
}
unsafe fn in_byte(port: u16) -> u8 {
    let ret: u8;
    asm!("inb %dx, %al" : "={al}"(ret) : "{dx}"(port) :: "volatile");
    ret
}
unsafe fn enable_interrupts() {
    asm!("sti" :::: "volatile");
}

unsafe fn send_eoi(interrupt_number: u64) {
    unsafe fn send_master_eoi() {out_byte(0x20, 0x20)}
    unsafe fn send_slave_eoi() {out_byte(0xA0, 0x20)}

    match interrupt_number {
        i if i >= 40 => {
            send_slave_eoi();
            send_master_eoi();
        },
        32...40 => send_master_eoi(),
        _ => {},
    }
}

#[no_mangle]
pub extern "C" fn interrupt_handler(interrupt_number: u64, error_code: u64, rsp:uint) {
    match interrupt_number {
        13 if error_code != 0 => panic!(
            "General Protection Fault: Segment error at segment 0x{:x}", error_code),
        32 => {},
        33 => print!("k"),
        50 => panic!("out of memory"),
        _ => panic!("unknown interrupt! number: {}, error_code: {:x}",interrupt_number, error_code),
    };
    unsafe{send_eoi(interrupt_number)};

    match interrupt_number {
        32 | 33 => unsafe{scheduler::reschedule(rsp)},
        _ => {},
    }
}

#[no_mangle]
pub extern "C" fn pagefault_handler(address: u64, error_code: u64, rsp:uint) {
    panic!("page fault: address: {:x}, error_code: {:b}, rsp: {:x}", address, error_code, rsp);
}

#[cfg(not(test))]
#[lang = "stack_exhausted"]
extern fn stack_exhausted() {panic!("stack exhausted");}

#[cfg(not(test))]
#[lang = "eh_personality"]
extern fn eh_personality() {unimplemented!();}

#[cfg(not(test))]
#[lang = "panic_fmt"]
fn panic_fmt() -> ! { unimplemented!();}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "C" fn _Unwind_Resume() -> ! {
    unimplemented!();
}
<commit_msg>add disable_interrupts(); end thread on interrupt 66; spawn 6 test threads (bug: even threads seem to get more computing time)<commit_after>#![no_std]
#![feature(globs, phase, asm, macro_rules, lang_items, default_type_params, unboxed_closures)]

#[cfg(test)] #[phase(plugin, link)] extern crate log;

#[cfg(not(test))] extern crate "os_alloc" as alloc;
#[cfg(test)] extern crate alloc;
extern crate unicode;
#[phase(plugin, link)] extern crate core;
#[cfg(not(test))] extern crate "os_collections" as core_collections;
#[cfg(test)] extern crate "collections" as core_collections;
extern crate "rand" as core_rand;
extern crate rlibc;
extern crate spinlock;

// Make std testable by not duplicating lang items. See #2912
#[cfg(test)] extern crate "std" as realstd;
#[cfg(test)] pub use realstd::kinds;
#[cfg(test)] pub use realstd::ops;
#[cfg(test)] pub use realstd::cmp;
#[cfg(test)] pub use realstd::boxed;

// NB: These reexports are in the order they should be listed in rustdoc

pub use core::any;
pub use core::borrow;
pub use core::cell;
pub use core::clone;
#[cfg(not(test))] pub use core::cmp;
pub use core::default;
pub use core::finally;
pub use core::intrinsics;
pub use core::iter;
#[cfg(not(test))] pub use core::kinds;
pub use core::mem;
#[cfg(not(test))] pub use core::ops;
pub use core::ptr;
pub use core::raw;
pub use core::simd;
pub use core::result;
pub use core::option;

#[cfg(not(test))] pub use alloc::boxed;
pub use alloc::rc;

pub use core_collections::slice;
pub use core_collections::str;
pub use core_collections::string;
pub use core_collections::vec;

pub use unicode::char;

use core::prelude::*;

/* Exported macros */

pub mod macros;

/* new for os */
mod multiboot;
mod init;
mod vga_buffer;
mod fn_box;
mod scheduler;
mod global;

pub mod fmt;

/* Common data structures */

pub mod collections;

// Documentation for primitive types

mod bool;
mod unit;
mod tuple;

#[no_mangle]
pub fn main(multiboot: *const multiboot::Information) {

    unsafe{init::frame_stack(multiboot)};
    global::init();
    unsafe{enable_interrupts()};

    print!("test\n\niuaeiae");
    let x = box 5i;

    let y = 0xb8000 as *mut u64;
    unsafe{*y = 0xffffffffffffffff};

    print!("test");
    print!("test\n");
    println!("newline {}", x);

    scheduler::spawn(|| print!("I'm #1!\n"));

    fn test(name: &str) {
        loop {
            let mut x = 0u;
            for i in range(0,100000) {
                x = i;
            }
            print!("{}", name);
        }
    }

    scheduler::spawn(|| test("1"));
    scheduler::spawn(|| test("2"));
    scheduler::spawn(|| test("3"));
    scheduler::spawn(|| test("4"));
    scheduler::spawn(|| test("5"));
    scheduler::spawn(|| test("6"));
    loop{
        let mut x = 0u;
            for i in range(0,100000) {
                x = i;
            }
        print!("m");
    }

    loop{}
    panic!("end of os!");
}

// A curious inner-module that's not exported that contains the binding
// 'std' so that macro-expanded references to std::error and such
// can be resolved within libstd.
#[doc(hidden)]
mod std {
    // mods used for deriving
    pub use clone;
    pub use cmp;
    //pub use hash;

    //pub use comm; // used for select!()
    //pub use error; // used for try!()
    pub use fmt; // used for any formatting strings
    //pub use io; // used for println!()
    pub use option; // used for bitflags!{}
    //pub use rt; // used for panic!()
    pub use vec; // used for vec![]
    pub use cell; // used for tls!
    //pub use thread_local; // used for thread_local!
    pub use kinds; // used for tls!

    // The test runner calls ::std::os::args() but really wants realstd
    #[cfg(test)] pub use realstd::os as os;
    // The test runner requires std::slice::Vector, so re-export std::slice just for it.
    //
    // It is also used in vec![]
    pub use slice;

    pub use boxed; // used for vec![]

}

/* Interrupt Handlers */

extern {
//    fn send_eoi(interrupt_number: u64) -> int; //return value to mark rax as used
}

unsafe fn out_byte(port: u16, data: u8) {
    asm!("outb %al, %dx" :: "{dx}"(port), "{al}"(data) :: "volatile");
}
unsafe fn in_byte(port: u16) -> u8 {
    let ret: u8;
    asm!("inb %dx, %al" : "={al}"(ret) : "{dx}"(port) :: "volatile");
    ret
}
unsafe fn enable_interrupts() {
    asm!("sti" :::: "volatile");
}
unsafe fn disable_interrupts() {
    asm!("cli" :::: "volatile");
}

unsafe fn send_eoi(interrupt_number: u64) {
    unsafe fn send_master_eoi() {out_byte(0x20, 0x20)}
    unsafe fn send_slave_eoi() {out_byte(0xA0, 0x20)}

    match interrupt_number {
        i if i >= 40 => {
            send_slave_eoi();
            send_master_eoi();
        },
        32...40 => send_master_eoi(),
        _ => {},
    }
}

#[no_mangle]
pub extern "C" fn interrupt_handler(interrupt_number: u64, error_code: u64, rsp:uint) {
    match interrupt_number {
        13 if error_code != 0 => panic!(
            "General Protection Fault: Segment error at segment 0x{:x}", error_code),
        32 => {},
        33 => print!("k"),
        50 => panic!("out of memory"),
        66 => println!("ending thread..."),
        _ => panic!("unknown interrupt! number: {}, error_code: {:x}",interrupt_number, error_code),
    };
    unsafe{send_eoi(interrupt_number)};

    match interrupt_number {
        32 => unsafe{scheduler::reschedule(rsp)},
        66 => unsafe{scheduler::schedule()},
        _ => {},
    }
}

#[no_mangle]
pub extern "C" fn pagefault_handler(address: u64, error_code: u64, rsp:uint) {
    panic!("page fault: address: {:x}, error_code: {:b}, rsp: {:x}", address, error_code, rsp);
}

#[cfg(not(test))]
#[lang = "stack_exhausted"]
extern fn stack_exhausted() {panic!("stack exhausted");}

#[cfg(not(test))]
#[lang = "eh_personality"]
extern fn eh_personality() {unimplemented!();}

#[cfg(not(test))]
#[lang = "panic_fmt"]
fn panic_fmt() -> ! { unimplemented!();}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "C" fn _Unwind_Resume() -> ! {
    unimplemented!();
}
<|endoftext|>