<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A mutable, nullable memory location

use cast::transmute_mut;
use prelude::*;

/*
A dynamic, mutable location.

Similar to a mutable option type, but friendlier.
*/

pub struct Cell<T> {
    priv value: Option<T>
}

impl<T:cmp::Eq> cmp::Eq for Cell<T> {
    fn eq(&self, other: &Cell<T>) -> bool {
        (self.value) == (other.value)
    }
    fn ne(&self, other: &Cell<T>) -> bool { !self.eq(other) }
}

/// Creates a new full cell with the given value.
pub fn Cell<T>(value: T) -> Cell<T> {
    Cell { value: Some(value) }
}

pub fn empty_cell<T>() -> Cell<T> {
    Cell { value: None }
}

pub impl<T> Cell<T> {
    /// Yields the value, failing if the cell is empty.
    fn take(&self) -> T {
        let mut self = unsafe { transmute_mut(self) };
        if self.is_empty() {
            fail!(~"attempt to take an empty cell");
        }

        let mut value = None;
        value <-> self.value;
        value.unwrap()
    }

    /// Returns the value, failing if the cell is full.
    fn put_back(&self, value: T) {
        let mut self = unsafe { transmute_mut(self) };
        if !self.is_empty() {
            fail!(~"attempt to put a value back into a full cell");
        }
        self.value = Some(value);
    }

    /// Returns true if the cell is empty and false if the cell is full.
    fn is_empty(&self) -> bool {
        self.value.is_none()
    }

    // Calls a closure with a reference to the value.
    fn with_ref<R>(&self, op: &fn(v: &T) -> R) -> R {
        let v = self.take();
        let r = op(&v);
        self.put_back(v);
        r
    }

    // Calls a closure with a mutable reference to the value.
    fn with_mut_ref<R>(&self, op: &fn(v: &mut T) -> R) -> R {
        let mut v = self.take();
        let r = op(&mut v);
        self.put_back(v);
        r
    }
}

#[test]
fn test_basic() {
    let value_cell = Cell(~10);
    assert!(!value_cell.is_empty());
    let value = value_cell.take();
    assert!(value == ~10);
    assert!(value_cell.is_empty());
    value_cell.put_back(value);
    assert!(!value_cell.is_empty());
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_take_empty() {
    let value_cell = empty_cell::<~int>();
    value_cell.take();
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_put_back_non_empty() {
    let value_cell = Cell(~10);
    value_cell.put_back(~20);
}

#[test]
fn test_with_ref() {
    let good = 6;
    let c = Cell(~[1, 2, 3, 4, 5, 6]);
    let l = do c.with_ref() |v| { v.len() };
    assert!(l == good);
}

#[test]
fn test_with_mut_ref() {
    let good = ~[1, 2, 3];
    let v = ~[1, 2];
    let c = Cell(v);
    do c.with_mut_ref() |v| { v.push(3); }
    let v = c.take();
    assert!(v == good);
}
<commit_msg>mark Cell as non-Const with #[mutable]<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A mutable, nullable memory location

use cast::transmute_mut;
use prelude::*;

/*
A dynamic, mutable location.

Similar to a mutable option type, but friendlier.
*/

#[mutable]
pub struct Cell<T> {
    priv value: Option<T>
}

impl<T:cmp::Eq> cmp::Eq for Cell<T> {
    fn eq(&self, other: &Cell<T>) -> bool {
        (self.value) == (other.value)
    }
    fn ne(&self, other: &Cell<T>) -> bool { !self.eq(other) }
}

/// Creates a new full cell with the given value.
pub fn Cell<T>(value: T) -> Cell<T> {
    Cell { value: Some(value) }
}

pub fn empty_cell<T>() -> Cell<T> {
    Cell { value: None }
}

pub impl<T> Cell<T> {
    /// Yields the value, failing if the cell is empty.
    fn take(&self) -> T {
        let mut self = unsafe { transmute_mut(self) };
        if self.is_empty() {
            fail!(~"attempt to take an empty cell");
        }

        let mut value = None;
        value <-> self.value;
        value.unwrap()
    }

    /// Returns the value, failing if the cell is full.
    fn put_back(&self, value: T) {
        let mut self = unsafe { transmute_mut(self) };
        if !self.is_empty() {
            fail!(~"attempt to put a value back into a full cell");
        }
        self.value = Some(value);
    }

    /// Returns true if the cell is empty and false if the cell is full.
    fn is_empty(&self) -> bool {
        self.value.is_none()
    }

    // Calls a closure with a reference to the value.
    fn with_ref<R>(&self, op: &fn(v: &T) -> R) -> R {
        let v = self.take();
        let r = op(&v);
        self.put_back(v);
        r
    }

    // Calls a closure with a mutable reference to the value.
    fn with_mut_ref<R>(&self, op: &fn(v: &mut T) -> R) -> R {
        let mut v = self.take();
        let r = op(&mut v);
        self.put_back(v);
        r
    }
}

#[test]
fn test_basic() {
    let value_cell = Cell(~10);
    assert!(!value_cell.is_empty());
    let value = value_cell.take();
    assert!(value == ~10);
    assert!(value_cell.is_empty());
    value_cell.put_back(value);
    assert!(!value_cell.is_empty());
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_take_empty() {
    let value_cell = empty_cell::<~int>();
    value_cell.take();
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_put_back_non_empty() {
    let value_cell = Cell(~10);
    value_cell.put_back(~20);
}

#[test]
fn test_with_ref() {
    let good = 6;
    let c = Cell(~[1, 2, 3, 4, 5, 6]);
    let l = do c.with_ref() |v| { v.len() };
    assert!(l == good);
}

#[test]
fn test_with_mut_ref() {
    let good = ~[1, 2, 3];
    let v = ~[1, 2];
    let c = Cell(v);
    do c.with_mut_ref() |v| { v.push(3); }
    let v = c.take();
    assert!(v == good);
}
<|endoftext|>


<commit_before>iface iterable<A> {
    fn iter(blk: fn(A));
}

impl<A> of iterable<A> for fn@(fn(A)) {
    fn iter(blk: fn(A)) {
        self(blk);
    }
}

// accomodate the fact that int/uint are passed by value by default:
impl of iterable<int> for fn@(fn(int)) {
    fn iter(blk: fn(&&int)) {
        self {|i| blk(i)}
    }
}

impl of iterable<uint> for fn@(fn(uint)) {
    fn iter(blk: fn(&&uint)) {
        self {|i| blk(i)}
    }
}

impl<A> of iterable<A> for [A] {
    fn iter(blk: fn(A)) {
        vec::iter(self, blk)
    }
}

impl<A> of iterable<A> for option<A> {
    fn iter(blk: fn(A)) {
        option::may(self, blk)
    }
}

impl of iterable<char> for str {
    fn iter(blk: fn(&&char)) {
        str::chars_iter(self) { |ch| blk(ch) }
    }
}

fn enumerate<A,IA:iterable<A>>(self: IA, blk: fn(uint, A)) {
    let mut i = 0u;
    self.iter {|a|
        blk(i, a);
        i += 1u;
    }
}

// Here: we have to use fn@ for predicates and map functions, because
// we will be binding them up into a closure.  Disappointing.  A true
// region type system might be able to do better than this.

fn filter<A,IA:iterable<A>>(self: IA, prd: fn@(A) -> bool, blk: fn(A)) {
    self.iter {|a|
        if prd(a) { blk(a) }
    }
}

fn filter_map<A,B,IA:iterable<A>>(self: IA, cnv: fn@(A) -> option<B>,
                                  blk: fn(B)) {
    self.iter {|a|
        alt cnv(a) {
          some(b) { blk(b) }
          none { }
        }
    }
}

fn map<A,B,IA:iterable<A>>(self: IA, cnv: fn@(A) -> B, blk: fn(B)) {
    self.iter {|a|
        let b = cnv(a);
        blk(b);
    }
}

fn flat_map<A,B,IA:iterable<A>,IB:iterable<B>>(
    self: IA, cnv: fn@(A) -> IB, blk: fn(B)) {
    self.iter {|a|
        cnv(a).iter(blk)
    }
}

fn foldl<A,B,IA:iterable<A>>(self: IA, +b0: B, blk: fn(-B, A) -> B) -> B {
    let mut b <- b0;
    self.iter {|a|
        b = blk(b, a);
    }
    ret b;
}

fn foldr<A:copy,B,IA:iterable<A>>(
    self: IA, +b0: B, blk: fn(A, -B) -> B) -> B {

    let mut b <- b0;
    reversed(self) {|a|
        b = blk(a, b);
    }
    ret b;
}

fn to_list<A:copy,IA:iterable<A>>(self: IA) -> [A] {
    foldl::<A,[A],IA>(self, [], {|r, a| r + [a]})
}

// FIXME: This could be made more efficient with an riterable interface
// #2005
fn reversed<A:copy,IA:iterable<A>>(self: IA, blk: fn(A)) {
    vec::riter(to_list(self), blk)
}

fn count<A,IA:iterable<A>>(self: IA, x: A) -> uint {
    foldl(self, 0u) {|count, value|
        if value == x {
            count + 1u
        } else {
            count
        }
    }
}

fn repeat(times: uint, blk: fn()) {
    let mut i = 0u;
    while i < times {
        blk();
        i += 1u;
    }
}

fn min<A:copy,IA:iterable<A>>(self: IA) -> A {
    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
        alt a {
          some(a_) if a_ < b {
            // FIXME: Not sure if this is successfully optimized to a move
            // #2005
            a
          }
          _ { some(b) }
        }
    } {
        some(val) { val }
        none { fail "min called on empty iterator" }
    }
}

fn max<A:copy,IA:iterable<A>>(self: IA) -> A {
    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
        alt a {
          some(a_) if a_ > b {
            // FIXME: Not sure if this is successfully optimized to a move
            // #2005
            a
          }
          _ { some(b) }
        }
    } {
        some(val) { val }
        none { fail "max called on empty iterator" }
    }
}

#[test]
fn test_enumerate() {
    enumerate(["0", "1", "2"]) {|i,j|
        assert #fmt["%u",i] == j;
    }
}

#[test]
fn test_map_and_to_list() {
    let a = bind vec::iter([0, 1, 2], _);
    let b = bind map(a, {|i| 2*i}, _);
    let c = to_list(b);
    assert c == [0, 2, 4];
}

#[test]
fn test_map_directly_on_vec() {
    let b = bind map([0, 1, 2], {|i| 2*i}, _);
    let c = to_list(b);
    assert c == [0, 2, 4];
}

#[test]
fn test_filter_on_int_range() {
    fn is_even(&&i: int) -> bool {
        ret (i % 2) == 0;
    }

    let l = to_list(bind filter(bind int::range(0, 10, _), is_even, _));
    assert l == [0, 2, 4, 6, 8];
}

#[test]
fn test_filter_on_uint_range() {
    fn is_even(&&i: uint) -> bool {
        ret (i % 2u) == 0u;
    }

    let l = to_list(bind filter(bind uint::range(0u, 10u, _), is_even, _));
    assert l == [0u, 2u, 4u, 6u, 8u];
}

#[test]
fn test_filter_map() {
    fn negativate_the_evens(&&i: int) -> option<int> {
        if i % 2 == 0 {
            some(-i)
        } else {
            none
        }
    }

    let l = to_list(bind filter_map(
        bind int::range(0, 5, _), negativate_the_evens, _));
    assert l == [0, -2, -4];
}

#[test]
fn test_flat_map_with_option() {
    fn if_even(&&i: int) -> option<int> {
        if (i % 2) == 0 { some(i) }
        else { none }
    }

    let a = bind vec::iter([0, 1, 2], _);
    let b = bind flat_map(a, if_even, _);
    let c = to_list(b);
    assert c == [0, 2];
}

#[test]
fn test_flat_map_with_list() {
    fn repeat(&&i: int) -> [int] {
        let mut r = [];
        int::range(0, i) {|_j| r += [i]; }
        r
    }

    let a = bind vec::iter([0, 1, 2, 3], _);
    let b = bind flat_map(a, repeat, _);
    let c = to_list(b);
    #debug["c = %?", c];
    assert c == [1, 2, 2, 3, 3, 3];
}

#[test]
fn test_repeat() {
    let mut c = [], i = 0u;
    repeat(5u) {||
        c += [(i * i)];
        i += 1u;
    };
    #debug["c = %?", c];
    assert c == [0u, 1u, 4u, 9u, 16u];
}

#[test]
fn test_min() {
    assert min([5, 4, 1, 2, 3]) == 1;
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_min_empty() {
    min::<int, [int]>([]);
}

#[test]
fn test_max() {
    assert max([1, 2, 4, 2, 3]) == 4;
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_max_empty() {
    max::<int, [int]>([]);
}

#[test]
fn test_reversed() {
    assert to_list(bind reversed([1, 2, 3], _)) == [3, 2, 1];
}

#[test]
fn test_count() {
    assert count([1, 2, 1, 2, 1], 1) == 3u;
}

#[test]
fn test_foldr() {
    fn sub(&&a: int, -b: int) -> int {
        a - b
    }
    let sum = foldr([1, 2, 3, 4], 0, sub);
    assert sum == -2;
}<commit_msg>core: Rename iter::to_list to to_vec. Closes #2056<commit_after>iface iterable<A> {
    fn iter(blk: fn(A));
}

impl<A> of iterable<A> for fn@(fn(A)) {
    fn iter(blk: fn(A)) {
        self(blk);
    }
}

// accomodate the fact that int/uint are passed by value by default:
impl of iterable<int> for fn@(fn(int)) {
    fn iter(blk: fn(&&int)) {
        self {|i| blk(i)}
    }
}

impl of iterable<uint> for fn@(fn(uint)) {
    fn iter(blk: fn(&&uint)) {
        self {|i| blk(i)}
    }
}

impl<A> of iterable<A> for [A] {
    fn iter(blk: fn(A)) {
        vec::iter(self, blk)
    }
}

impl<A> of iterable<A> for option<A> {
    fn iter(blk: fn(A)) {
        option::may(self, blk)
    }
}

impl of iterable<char> for str {
    fn iter(blk: fn(&&char)) {
        str::chars_iter(self) { |ch| blk(ch) }
    }
}

fn enumerate<A,IA:iterable<A>>(self: IA, blk: fn(uint, A)) {
    let mut i = 0u;
    self.iter {|a|
        blk(i, a);
        i += 1u;
    }
}

// Here: we have to use fn@ for predicates and map functions, because
// we will be binding them up into a closure.  Disappointing.  A true
// region type system might be able to do better than this.

fn filter<A,IA:iterable<A>>(self: IA, prd: fn@(A) -> bool, blk: fn(A)) {
    self.iter {|a|
        if prd(a) { blk(a) }
    }
}

fn filter_map<A,B,IA:iterable<A>>(self: IA, cnv: fn@(A) -> option<B>,
                                  blk: fn(B)) {
    self.iter {|a|
        alt cnv(a) {
          some(b) { blk(b) }
          none { }
        }
    }
}

fn map<A,B,IA:iterable<A>>(self: IA, cnv: fn@(A) -> B, blk: fn(B)) {
    self.iter {|a|
        let b = cnv(a);
        blk(b);
    }
}

fn flat_map<A,B,IA:iterable<A>,IB:iterable<B>>(
    self: IA, cnv: fn@(A) -> IB, blk: fn(B)) {
    self.iter {|a|
        cnv(a).iter(blk)
    }
}

fn foldl<A,B,IA:iterable<A>>(self: IA, +b0: B, blk: fn(-B, A) -> B) -> B {
    let mut b <- b0;
    self.iter {|a|
        b = blk(b, a);
    }
    ret b;
}

fn foldr<A:copy,B,IA:iterable<A>>(
    self: IA, +b0: B, blk: fn(A, -B) -> B) -> B {

    let mut b <- b0;
    reversed(self) {|a|
        b = blk(a, b);
    }
    ret b;
}

fn to_vec<A:copy,IA:iterable<A>>(self: IA) -> [A] {
    foldl::<A,[A],IA>(self, [], {|r, a| r + [a]})
}

// FIXME: This could be made more efficient with an riterable interface
// #2005
fn reversed<A:copy,IA:iterable<A>>(self: IA, blk: fn(A)) {
    vec::riter(to_vec(self), blk)
}

fn count<A,IA:iterable<A>>(self: IA, x: A) -> uint {
    foldl(self, 0u) {|count, value|
        if value == x {
            count + 1u
        } else {
            count
        }
    }
}

fn repeat(times: uint, blk: fn()) {
    let mut i = 0u;
    while i < times {
        blk();
        i += 1u;
    }
}

fn min<A:copy,IA:iterable<A>>(self: IA) -> A {
    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
        alt a {
          some(a_) if a_ < b {
            // FIXME: Not sure if this is successfully optimized to a move
            // #2005
            a
          }
          _ { some(b) }
        }
    } {
        some(val) { val }
        none { fail "min called on empty iterator" }
    }
}

fn max<A:copy,IA:iterable<A>>(self: IA) -> A {
    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
        alt a {
          some(a_) if a_ > b {
            // FIXME: Not sure if this is successfully optimized to a move
            // #2005
            a
          }
          _ { some(b) }
        }
    } {
        some(val) { val }
        none { fail "max called on empty iterator" }
    }
}

#[test]
fn test_enumerate() {
    enumerate(["0", "1", "2"]) {|i,j|
        assert #fmt["%u",i] == j;
    }
}

#[test]
fn test_map_and_to_vec() {
    let a = bind vec::iter([0, 1, 2], _);
    let b = bind map(a, {|i| 2*i}, _);
    let c = to_vec(b);
    assert c == [0, 2, 4];
}

#[test]
fn test_map_directly_on_vec() {
    let b = bind map([0, 1, 2], {|i| 2*i}, _);
    let c = to_vec(b);
    assert c == [0, 2, 4];
}

#[test]
fn test_filter_on_int_range() {
    fn is_even(&&i: int) -> bool {
        ret (i % 2) == 0;
    }

    let l = to_vec(bind filter(bind int::range(0, 10, _), is_even, _));
    assert l == [0, 2, 4, 6, 8];
}

#[test]
fn test_filter_on_uint_range() {
    fn is_even(&&i: uint) -> bool {
        ret (i % 2u) == 0u;
    }

    let l = to_vec(bind filter(bind uint::range(0u, 10u, _), is_even, _));
    assert l == [0u, 2u, 4u, 6u, 8u];
}

#[test]
fn test_filter_map() {
    fn negativate_the_evens(&&i: int) -> option<int> {
        if i % 2 == 0 {
            some(-i)
        } else {
            none
        }
    }

    let l = to_vec(bind filter_map(
        bind int::range(0, 5, _), negativate_the_evens, _));
    assert l == [0, -2, -4];
}

#[test]
fn test_flat_map_with_option() {
    fn if_even(&&i: int) -> option<int> {
        if (i % 2) == 0 { some(i) }
        else { none }
    }

    let a = bind vec::iter([0, 1, 2], _);
    let b = bind flat_map(a, if_even, _);
    let c = to_vec(b);
    assert c == [0, 2];
}

#[test]
fn test_flat_map_with_list() {
    fn repeat(&&i: int) -> [int] {
        let mut r = [];
        int::range(0, i) {|_j| r += [i]; }
        r
    }

    let a = bind vec::iter([0, 1, 2, 3], _);
    let b = bind flat_map(a, repeat, _);
    let c = to_vec(b);
    #debug["c = %?", c];
    assert c == [1, 2, 2, 3, 3, 3];
}

#[test]
fn test_repeat() {
    let mut c = [], i = 0u;
    repeat(5u) {||
        c += [(i * i)];
        i += 1u;
    };
    #debug["c = %?", c];
    assert c == [0u, 1u, 4u, 9u, 16u];
}

#[test]
fn test_min() {
    assert min([5, 4, 1, 2, 3]) == 1;
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_min_empty() {
    min::<int, [int]>([]);
}

#[test]
fn test_max() {
    assert max([1, 2, 4, 2, 3]) == 4;
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_max_empty() {
    max::<int, [int]>([]);
}

#[test]
fn test_reversed() {
    assert to_vec(bind reversed([1, 2, 3], _)) == [3, 2, 1];
}

#[test]
fn test_count() {
    assert count([1, 2, 1, 2, 1], 1) == 3u;
}

#[test]
fn test_foldr() {
    fn sub(&&a: int, -b: int) -> int {
        a - b
    }
    let sum = foldr([1, 2, 3, 4], 0, sub);
    assert sum == -2;
}<|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*! The Clone trait for types that cannot be "implicitly copied"

In Rust, some simple types are "implicitly copyable" and when you
assign them or pass them as arguments, the receiver will get a copy,
leaving the original value in place. These types do not require
allocation to copy and do not have finalizers (i.e. they do not
contain owned boxes or implement `Drop`), so the compiler considers
them cheap and safe to copy. For other types copies must be made
explicitly, by convention implementing the `Clone` trait and calling
the `clone` method.

*/

use std::kinds::Freeze;

/// A common trait for cloning an object.
pub trait Clone {
    /// Returns a copy of the value. The contents of owned pointers
    /// are copied to maintain uniqueness, while the contents of
    /// managed pointers are not copied.
    fn clone(&self) -> Self;

    /// Perform copy-assignment from `source`.
    ///
    /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
    /// but can be overriden to reuse the resources of `a` to avoid unnecessary
    /// allocations.
    #[inline(always)]
    fn clone_from(&mut self, source: &Self) {
        *self = source.clone()
    }
}

impl<T: Clone> Clone for ~T {
    /// Return a copy of the owned box.
    #[inline]
    fn clone(&self) -> ~T { ~(**self).clone() }

    /// Perform copy-assignment from `source` by reusing the existing allocation.
    fn clone_from(&mut self, source: &~T) {
        **self = (**source).clone()
    }
}

impl<T> Clone for @T {
    /// Return a shallow copy of the managed box.
    #[inline]
    fn clone(&self) -> @T { *self }
}

impl<T> Clone for @mut T {
    /// Return a shallow copy of the managed box.
    #[inline]
    fn clone(&self) -> @mut T { *self }
}

impl<'self, T> Clone for &'self T {
    /// Return a shallow copy of the borrowed pointer.
    #[inline]
    fn clone(&self) -> &'self T { *self }
}

impl<'self, T> Clone for &'self [T] {
    /// Return a shallow copy of the slice.
    #[inline]
    fn clone(&self) -> &'self [T] { *self }
}

impl<'self> Clone for &'self str {
    /// Return a shallow copy of the slice.
    #[inline]
    fn clone(&self) -> &'self str { *self }
}

macro_rules! clone_impl(
    ($t:ty) => {
        impl Clone for $t {
            /// Return a deep copy of the value.
            #[inline]
            fn clone(&self) -> $t { *self }
        }
    }
)

clone_impl!(int)
clone_impl!(i8)
clone_impl!(i16)
clone_impl!(i32)
clone_impl!(i64)

clone_impl!(uint)
clone_impl!(u8)
clone_impl!(u16)
clone_impl!(u32)
clone_impl!(u64)

clone_impl!(f32)
clone_impl!(f64)

clone_impl!(())
clone_impl!(bool)
clone_impl!(char)

macro_rules! extern_fn_clone(
    ($($A:ident),*) => (
        impl<$($A,)* ReturnType> Clone for extern "Rust" fn($($A),*) -> ReturnType {
            /// Return a copy of a function pointer
            #[inline]
            fn clone(&self) -> extern "Rust" fn($($A),*) -> ReturnType { *self }
        }
    )
)

extern_fn_clone!()
extern_fn_clone!(A)
extern_fn_clone!(A, B)
extern_fn_clone!(A, B, C)
extern_fn_clone!(A, B, C, D)
extern_fn_clone!(A, B, C, D, E)
extern_fn_clone!(A, B, C, D, E, F)
extern_fn_clone!(A, B, C, D, E, F, G)
extern_fn_clone!(A, B, C, D, E, F, G, H)

/// A trait distinct from `Clone` which represents "deep copies" of things like
/// managed boxes which would otherwise not be copied.
pub trait DeepClone {
    /// Return a deep copy of the value. Unlike `Clone`, the contents of shared pointer types
    /// *are* copied.
    fn deep_clone(&self) -> Self;

    /// Perform deep copy-assignment from `source`.
    ///
    /// `a.deep_clone_from(&b)` is equivalent to `a = b.deep_clone()` in
    /// functionality, but can be overriden to reuse the resources of `a` to
    /// avoid unnecessary allocations.
    #[inline(always)]
    fn deep_clone_from(&mut self, source: &Self) {
        *self = source.deep_clone()
    }
}

impl<T: DeepClone> DeepClone for ~T {
    /// Return a deep copy of the owned box.
    #[inline]
    fn deep_clone(&self) -> ~T { ~(**self).deep_clone() }

    /// Perform deep copy-assignment from `source` by reusing the existing allocation.
    fn deep_clone_from(&mut self, source: &~T) {
        **self = (**source).deep_clone()
    }
}

// FIXME: #6525: should also be implemented for `T: Send + DeepClone`
impl<T: Freeze + DeepClone + 'static> DeepClone for @T {
    /// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing
    /// a deep clone of a potentially cyclical type.
    #[inline]
    fn deep_clone(&self) -> @T { @(**self).deep_clone() }
}

// FIXME: #6525: should also be implemented for `T: Send + DeepClone`
impl<T: Freeze + DeepClone + 'static> DeepClone for @mut T {
    /// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing
    /// a deep clone of a potentially cyclical type.
    #[inline]
    fn deep_clone(&self) -> @mut T { @mut (**self).deep_clone() }
}

macro_rules! deep_clone_impl(
    ($t:ty) => {
        impl DeepClone for $t {
            /// Return a deep copy of the value.
            #[inline]
            fn deep_clone(&self) -> $t { *self }
        }
    }
)

deep_clone_impl!(int)
deep_clone_impl!(i8)
deep_clone_impl!(i16)
deep_clone_impl!(i32)
deep_clone_impl!(i64)

deep_clone_impl!(uint)
deep_clone_impl!(u8)
deep_clone_impl!(u16)
deep_clone_impl!(u32)
deep_clone_impl!(u64)

deep_clone_impl!(f32)
deep_clone_impl!(f64)

deep_clone_impl!(())
deep_clone_impl!(bool)
deep_clone_impl!(char)

macro_rules! extern_fn_deep_clone(
    ($($A:ident),*) => (
        impl<$($A,)* ReturnType> DeepClone for extern "Rust" fn($($A),*) -> ReturnType {
            /// Return a copy of a function pointer
            #[inline]
            fn deep_clone(&self) -> extern "Rust" fn($($A),*) -> ReturnType { *self }
        }
    )
)

extern_fn_deep_clone!()
extern_fn_deep_clone!(A)
extern_fn_deep_clone!(A, B)
extern_fn_deep_clone!(A, B, C)
extern_fn_deep_clone!(A, B, C, D)
extern_fn_deep_clone!(A, B, C, D, E)
extern_fn_deep_clone!(A, B, C, D, E, F)
extern_fn_deep_clone!(A, B, C, D, E, F, G)
extern_fn_deep_clone!(A, B, C, D, E, F, G, H)

#[test]
fn test_owned_clone() {
    let a = ~5i;
    let b: ~int = a.clone();
    assert_eq!(a, b);
}

#[test]
fn test_managed_clone() {
    let a = @5i;
    let b: @int = a.clone();
    assert_eq!(a, b);
}

#[test]
fn test_managed_mut_deep_clone() {
    let x = @mut 5i;
    let y: @mut int = x.deep_clone();
    *x = 20;
    assert_eq!(*y, 5);
}

#[test]
fn test_managed_mut_clone() {
    let a = @mut 5i;
    let b: @mut int = a.clone();
    assert_eq!(a, b);
    *b = 10;
    assert_eq!(a, b);
}

#[test]
fn test_borrowed_clone() {
    let x = 5i;
    let y: &int = &x;
    let z: &int = (&y).clone();
    assert_eq!(*z, 5);
}

#[test]
fn test_clone_from() {
    let a = ~5;
    let mut b = ~10;
    b.clone_from(&a);
    assert_eq!(*b, 5);
}

#[test]
fn test_deep_clone_from() {
    let a = ~5;
    let mut b = ~10;
    b.deep_clone_from(&a);
    assert_eq!(*b, 5);
}

#[test]
fn test_extern_fn_clone() {
    trait Empty {}
    impl Empty for int {}

    fn test_fn_a() -> f64 { 1.0 }
    fn test_fn_b<T: Empty>(x: T) -> T { x }
    fn test_fn_c(_: int, _: f64, _: ~[int], _: int, _: int, _: int) {}

    let _ = test_fn_a.clone();
    let _ = test_fn_b::<int>.clone();
    let _ = test_fn_c.clone();

    let _ = test_fn_a.deep_clone();
    let _ = test_fn_b::<int>.deep_clone();
    let _ = test_fn_c.deep_clone();
}
<commit_msg>make DeepClone inherit from Clone<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*! The Clone trait for types that cannot be "implicitly copied"

In Rust, some simple types are "implicitly copyable" and when you
assign them or pass them as arguments, the receiver will get a copy,
leaving the original value in place. These types do not require
allocation to copy and do not have finalizers (i.e. they do not
contain owned boxes or implement `Drop`), so the compiler considers
them cheap and safe to copy. For other types copies must be made
explicitly, by convention implementing the `Clone` trait and calling
the `clone` method.

*/

use std::kinds::Freeze;

/// A common trait for cloning an object.
pub trait Clone {
    /// Returns a copy of the value. The contents of owned pointers
    /// are copied to maintain uniqueness, while the contents of
    /// managed pointers are not copied.
    fn clone(&self) -> Self;

    /// Perform copy-assignment from `source`.
    ///
    /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
    /// but can be overriden to reuse the resources of `a` to avoid unnecessary
    /// allocations.
    #[inline(always)]
    fn clone_from(&mut self, source: &Self) {
        *self = source.clone()
    }
}

impl<T: Clone> Clone for ~T {
    /// Return a copy of the owned box.
    #[inline]
    fn clone(&self) -> ~T { ~(**self).clone() }

    /// Perform copy-assignment from `source` by reusing the existing allocation.
    fn clone_from(&mut self, source: &~T) {
        **self = (**source).clone()
    }
}

impl<T> Clone for @T {
    /// Return a shallow copy of the managed box.
    #[inline]
    fn clone(&self) -> @T { *self }
}

impl<T> Clone for @mut T {
    /// Return a shallow copy of the managed box.
    #[inline]
    fn clone(&self) -> @mut T { *self }
}

impl<'self, T> Clone for &'self T {
    /// Return a shallow copy of the borrowed pointer.
    #[inline]
    fn clone(&self) -> &'self T { *self }
}

impl<'self, T> Clone for &'self [T] {
    /// Return a shallow copy of the slice.
    #[inline]
    fn clone(&self) -> &'self [T] { *self }
}

impl<'self> Clone for &'self str {
    /// Return a shallow copy of the slice.
    #[inline]
    fn clone(&self) -> &'self str { *self }
}

macro_rules! clone_impl(
    ($t:ty) => {
        impl Clone for $t {
            /// Return a deep copy of the value.
            #[inline]
            fn clone(&self) -> $t { *self }
        }
    }
)

clone_impl!(int)
clone_impl!(i8)
clone_impl!(i16)
clone_impl!(i32)
clone_impl!(i64)

clone_impl!(uint)
clone_impl!(u8)
clone_impl!(u16)
clone_impl!(u32)
clone_impl!(u64)

clone_impl!(f32)
clone_impl!(f64)

clone_impl!(())
clone_impl!(bool)
clone_impl!(char)

macro_rules! extern_fn_clone(
    ($($A:ident),*) => (
        impl<$($A,)* ReturnType> Clone for extern "Rust" fn($($A),*) -> ReturnType {
            /// Return a copy of a function pointer
            #[inline]
            fn clone(&self) -> extern "Rust" fn($($A),*) -> ReturnType { *self }
        }
    )
)

extern_fn_clone!()
extern_fn_clone!(A)
extern_fn_clone!(A, B)
extern_fn_clone!(A, B, C)
extern_fn_clone!(A, B, C, D)
extern_fn_clone!(A, B, C, D, E)
extern_fn_clone!(A, B, C, D, E, F)
extern_fn_clone!(A, B, C, D, E, F, G)
extern_fn_clone!(A, B, C, D, E, F, G, H)

/// A trait distinct from `Clone` which represents "deep copies" of things like
/// managed boxes which would otherwise not be copied.
pub trait DeepClone: Clone {
    /// Return a deep copy of the value. Unlike `Clone`, the contents of shared pointer types
    /// *are* copied.
    fn deep_clone(&self) -> Self;

    /// Perform deep copy-assignment from `source`.
    ///
    /// `a.deep_clone_from(&b)` is equivalent to `a = b.deep_clone()` in
    /// functionality, but can be overriden to reuse the resources of `a` to
    /// avoid unnecessary allocations.
    #[inline(always)]
    fn deep_clone_from(&mut self, source: &Self) {
        *self = source.deep_clone()
    }
}

impl<T: DeepClone> DeepClone for ~T {
    /// Return a deep copy of the owned box.
    #[inline]
    fn deep_clone(&self) -> ~T { ~(**self).deep_clone() }

    /// Perform deep copy-assignment from `source` by reusing the existing allocation.
    fn deep_clone_from(&mut self, source: &~T) {
        **self = (**source).deep_clone()
    }
}

// FIXME: #6525: should also be implemented for `T: Send + DeepClone`
impl<T: Freeze + DeepClone + 'static> DeepClone for @T {
    /// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing
    /// a deep clone of a potentially cyclical type.
    #[inline]
    fn deep_clone(&self) -> @T { @(**self).deep_clone() }
}

// FIXME: #6525: should also be implemented for `T: Send + DeepClone`
impl<T: Freeze + DeepClone + 'static> DeepClone for @mut T {
    /// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing
    /// a deep clone of a potentially cyclical type.
    #[inline]
    fn deep_clone(&self) -> @mut T { @mut (**self).deep_clone() }
}

macro_rules! deep_clone_impl(
    ($t:ty) => {
        impl DeepClone for $t {
            /// Return a deep copy of the value.
            #[inline]
            fn deep_clone(&self) -> $t { *self }
        }
    }
)

deep_clone_impl!(int)
deep_clone_impl!(i8)
deep_clone_impl!(i16)
deep_clone_impl!(i32)
deep_clone_impl!(i64)

deep_clone_impl!(uint)
deep_clone_impl!(u8)
deep_clone_impl!(u16)
deep_clone_impl!(u32)
deep_clone_impl!(u64)

deep_clone_impl!(f32)
deep_clone_impl!(f64)

deep_clone_impl!(())
deep_clone_impl!(bool)
deep_clone_impl!(char)

macro_rules! extern_fn_deep_clone(
    ($($A:ident),*) => (
        impl<$($A,)* ReturnType> DeepClone for extern "Rust" fn($($A),*) -> ReturnType {
            /// Return a copy of a function pointer
            #[inline]
            fn deep_clone(&self) -> extern "Rust" fn($($A),*) -> ReturnType { *self }
        }
    )
)

extern_fn_deep_clone!()
extern_fn_deep_clone!(A)
extern_fn_deep_clone!(A, B)
extern_fn_deep_clone!(A, B, C)
extern_fn_deep_clone!(A, B, C, D)
extern_fn_deep_clone!(A, B, C, D, E)
extern_fn_deep_clone!(A, B, C, D, E, F)
extern_fn_deep_clone!(A, B, C, D, E, F, G)
extern_fn_deep_clone!(A, B, C, D, E, F, G, H)

#[test]
fn test_owned_clone() {
    let a = ~5i;
    let b: ~int = a.clone();
    assert_eq!(a, b);
}

#[test]
fn test_managed_clone() {
    let a = @5i;
    let b: @int = a.clone();
    assert_eq!(a, b);
}

#[test]
fn test_managed_mut_deep_clone() {
    let x = @mut 5i;
    let y: @mut int = x.deep_clone();
    *x = 20;
    assert_eq!(*y, 5);
}

#[test]
fn test_managed_mut_clone() {
    let a = @mut 5i;
    let b: @mut int = a.clone();
    assert_eq!(a, b);
    *b = 10;
    assert_eq!(a, b);
}

#[test]
fn test_borrowed_clone() {
    let x = 5i;
    let y: &int = &x;
    let z: &int = (&y).clone();
    assert_eq!(*z, 5);
}

#[test]
fn test_clone_from() {
    let a = ~5;
    let mut b = ~10;
    b.clone_from(&a);
    assert_eq!(*b, 5);
}

#[test]
fn test_deep_clone_from() {
    let a = ~5;
    let mut b = ~10;
    b.deep_clone_from(&a);
    assert_eq!(*b, 5);
}

#[test]
fn test_extern_fn_clone() {
    trait Empty {}
    impl Empty for int {}

    fn test_fn_a() -> f64 { 1.0 }
    fn test_fn_b<T: Empty>(x: T) -> T { x }
    fn test_fn_c(_: int, _: f64, _: ~[int], _: int, _: int, _: int) {}

    let _ = test_fn_a.clone();
    let _ = test_fn_b::<int>.clone();
    let _ = test_fn_c.clone();

    let _ = test_fn_a.deep_clone();
    let _ = test_fn_b::<int>.deep_clone();
    let _ = test_fn_c.deep_clone();
}
<|endoftext|>


<commit_before>use std::ffi::{CString, CStr};
use std::os::raw::{c_char, c_uint};
use std::{mem, ptr};
use std::cell::RefCell;

use llvm_sys;
use llvm_sys::prelude::*;
use llvm_sys::core::*;
use llvm_sys::target;
use llvm_sys::analysis::{LLVMVerifyModule, LLVMVerifierFailureAction};
use llvm_sys::transforms::pass_manager_builder as builder;
use llvm_sys::execution_engine as engine;
pub use llvm_sys::LLVMIntPredicate;

// FIXME: Force to link against libffi
#[link(name = "ffi")]
extern {}

pub struct Context {
    context_ref: LLVMContextRef,
    strings:     RefCell<Vec<CString>>,
}

impl Context {
    pub fn new() -> Self {
        Context {
            context_ref: unsafe { LLVMContextCreate() },
            strings:     RefCell::new(Vec::new()),
        }
    }

    pub fn new_name(&self, name: &str) -> *const c_char {
        let string = CString::new(name).unwrap();
        let ptr    = string.as_ptr();
        self.strings.borrow_mut().push(string);
        ptr
    }

    fn wrap_value(&self, value_ref: LLVMValueRef) -> Value {
        Value {
            value_ref: value_ref,
            context:   self,
        }
    }

    fn wrap_type(&self, type_ref: LLVMTypeRef) -> Type {
        Type {
            type_ref: type_ref,
            context:  self,
        }
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            LLVMContextDispose(self.context_ref);
        }
    }
}

#[derive(Clone, Copy)]
pub struct Module<'a> {
    module_ref: LLVMModuleRef,
    context:    &'a Context,
}

impl<'a> Module<'a> {
    pub fn new(context: &'a Context, name: &str) -> Self {
        let name = context.new_name(name);
        Module {
            module_ref: unsafe {
                LLVMModuleCreateWithNameInContext(name, context.context_ref)
            },
            context: context,
        }
    }

    pub fn add_function(&self, name: &str, ty: Type<'a>) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMAddFunction(self.module_ref, name, ty.type_ref)
        })
    }

    // From llvm-alt:
    pub fn optimize(&self, opt_level: usize, size_level: usize) {
        unsafe {
            let builder = builder::LLVMPassManagerBuilderCreate();
            builder::LLVMPassManagerBuilderSetOptLevel(builder, opt_level as _);
            builder::LLVMPassManagerBuilderSetSizeLevel(builder, size_level as _);
            let pass_manager = LLVMCreatePassManager();
            builder::LLVMPassManagerBuilderPopulateModulePassManager(builder, pass_manager);
            builder::LLVMPassManagerBuilderDispose(builder);
            LLVMRunPassManager(pass_manager, self.module_ref);
            LLVMDisposePassManager(pass_manager);
        }
    }

    pub fn dump(&self) {
        unsafe {
            LLVMDumpModule(self.module_ref);
        }
    }

    pub fn verify(&self) -> Result<(), String> {
        let mut out_message: *mut c_char = ptr::null_mut();

        unsafe {
            if LLVMVerifyModule(self.module_ref,
                                LLVMVerifierFailureAction::LLVMReturnStatusAction,
                                &mut out_message) == 0 {
                Ok(())
            } else {
                let result = CStr::from_ptr(out_message).to_string_lossy().into_owned();
                LLVMDisposeMessage(out_message);
                Err(result)
            }
        }
    }

    pub fn run_function(&self, name: &str) -> Result<u64, String> {
        let mut out_message: *mut c_char = ptr::null_mut();
        let mut exec: engine::LLVMExecutionEngineRef = ptr::null_mut();

        unsafe {
            engine::LLVMLinkInMCJIT();

            if target::LLVM_InitializeNativeAsmPrinter() == 1 {
                return Err("Could not initialize native asm printer for LLVM.".to_owned());
            }

            if target::LLVM_InitializeNativeTarget() == 1 {
                return Err("Could not initialize native target for LLVM.".to_owned());
            }

            let mut options = engine::LLVMMCJITCompilerOptions {
                OptLevel: 3,
                CodeModel: llvm_sys::target_machine::LLVMCodeModel::LLVMCodeModelDefault,
                NoFramePointerElim: 0,
                EnableFastISel: 0,
                MCJMM: ptr::null_mut(),
            };

            if engine::LLVMCreateMCJITCompilerForModule(
                &mut exec, self.module_ref,
                &mut options,
                mem::size_of::<c_uint>() as _,
                &mut out_message
            ) != 0 {
                let result = CStr::from_ptr(out_message).to_string_lossy().into_owned();
                LLVMDisposeMessage(out_message);
                return Err(result);
            }

            let cname    = CString::new(name).unwrap();
            let fun_addr = engine::LLVMGetFunctionAddress(exec, cname.as_ptr());
            let fun: extern fn() -> u64 = mem::transmute(fun_addr);

            Ok(fun())
        }
    }
}

#[derive(Copy, Clone)]
pub struct Type<'a> {
    type_ref:  LLVMTypeRef,
    context:   &'a Context,
}

impl<'a> Type<'a> {
    pub fn get_i64(context: &'a Context) -> Self {
        context.wrap_type(unsafe {
            LLVMInt64TypeInContext(context.context_ref)
        })
    }

    pub fn get_i32(context: &'a Context) -> Self {
        context.wrap_type(unsafe {
            LLVMInt32TypeInContext(context.context_ref)
        })
    }

    pub fn get_i8(context: &'a Context) -> Self {
        context.wrap_type(unsafe {
            LLVMInt8TypeInContext(context.context_ref)
        })
    }

    pub fn get_bool(context: &'a Context) -> Self {
        context.wrap_type(unsafe {
            LLVMInt1TypeInContext(context.context_ref)
        })
    }

    pub fn get_void(context: &'a Context) -> Self {
        context.wrap_type(unsafe {
            LLVMVoidTypeInContext(context.context_ref)
        })
    }

    pub fn get_pointer(target: Type<'a>) -> Self {
        target.context.wrap_type(unsafe {
            LLVMPointerType(target.type_ref, 0)
        })
    }

    pub fn get_function(args: &[Type<'a>], result: Type<'a>) -> Self {
        let mut args = args.into_iter().map(|arg| arg.type_ref).collect::<Vec<_>>();
        result.context.wrap_type(unsafe {
            LLVMFunctionType(result.type_ref,
                             args.as_mut_ptr(),
                             args.len() as _,
                             0)
        })
    }
}

#[derive(Copy, Clone)]
pub struct Value<'a> {
    value_ref: LLVMValueRef,
    context:   &'a Context,
}

impl<'a> Value<'a> {
//    pub fn get_fun_param(&self, index: usize) -> Self {
//        self.context.wrap_value(unsafe {
//            LLVMGetParam(self.value_ref, index as _)
//        })
//    }

    pub fn append(&self, name: &str) -> BasicBlock<'a> {
        let name = self.context.new_name(name);
        let bb_ref = unsafe {
            LLVMAppendBasicBlockInContext(self.context.context_ref,
                                          self.value_ref,
                                          name)
        };
        BasicBlock {
            bb_ref: bb_ref,
            _context: self.context,
        }
    }

    pub fn get_u64(context: &'a Context, value: u64) -> Self {
        context.wrap_value(unsafe {
            LLVMConstInt(Type::get_i64(context).type_ref,
                         value as _,
                         false as _)
        })
    }

    pub fn get_u32(context: &'a Context, value: u32) -> Self {
        context.wrap_value(unsafe {
            LLVMConstInt(Type::get_i32(context).type_ref,
                         value as _,
                         false as _)
        })
    }

    pub fn get_u8(context: &'a Context, value: u8) -> Self {
        context.wrap_value(unsafe {
            LLVMConstInt(Type::get_i8(context).type_ref,
                         value as _,
                         false as _)
        })
    }

    pub fn get_bool(context: &'a Context, value: bool) -> Self {
        context.wrap_value(unsafe {
            LLVMConstInt(Type::get_bool(context).type_ref,
                         value as _,
                         false as _)
        })
    }
}

#[derive(Copy, Clone)]
pub struct BasicBlock<'a> {
    bb_ref:  LLVMBasicBlockRef,
    _context: &'a Context,
}

#[derive(Copy, Clone)]
pub struct Builder<'a> {
    builder_ref: LLVMBuilderRef,
    context:     &'a Context,
}

impl<'a> Builder<'a> {
    pub fn new(context: &'a Context) -> Self {
        Builder {
            builder_ref: unsafe { LLVMCreateBuilderInContext(context.context_ref) },
            context:     context,
        }
    }

    pub fn position_at_end(&self, bb: BasicBlock<'a>) {
        unsafe {
            LLVMPositionBuilderAtEnd(self.builder_ref, bb.bb_ref);
        }
    }

    pub fn add(&self, v1: Value<'a>, v2: Value<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildAdd(self.builder_ref, v1.value_ref, v2.value_ref, name)
        })
    }

    pub fn alloca(&self, ty: Type<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildAlloca(self.builder_ref, ty.type_ref, name)
        })
    }

    pub fn array_alloca(&self, ty: Type<'a>, size: Value<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildArrayAlloca(self.builder_ref,
                                 ty.type_ref,
                                 size.value_ref,
                                 name)
        })
    }

    pub fn br(&self, dst: BasicBlock<'a>) {
        unsafe {
            LLVMBuildBr(self.builder_ref, dst.bb_ref);
        }
    }

    pub fn call(&self, fun: Value<'a>, args: &[Value<'a>], name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        let mut args = args.into_iter().map(|arg| arg.value_ref).collect::<Vec<_>>();
        self.context.wrap_value(unsafe {
            LLVMBuildCall(self.builder_ref,
                          fun.value_ref,
                          args.as_mut_ptr(),
                          args.len() as u32,
                          name)
        })
    }

    pub fn cmp(&self, pred: LLVMIntPredicate, lhs: Value<'a>, rhs: Value<'a>,
               name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildICmp(self.builder_ref, pred, lhs.value_ref, rhs.value_ref, name)

        })
    }

    pub fn cond_br(&self, test: Value<'a>, then: BasicBlock<'a>, else_: BasicBlock<'a>) {
        unsafe {
            LLVMBuildCondBr(self.builder_ref, test.value_ref, then.bb_ref, else_.bb_ref);
        }
    }

    pub fn gep(&self, ptr: Value<'a>, indices: &[Value<'a>], name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        let mut indices = indices.into_iter().map(|i| i.value_ref).collect::<Vec<_>>();
        self.context.wrap_value(unsafe {
            LLVMBuildGEP(self.builder_ref,
                         ptr.value_ref,
                         indices.as_mut_ptr(),
                         indices.len() as u32,
                         name)
        })
    }

    pub fn load(&self, ptr: Value<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildLoad(self.builder_ref, ptr.value_ref, name)
        })
    }

    pub fn ret(&self, value: Value<'a>) {
        unsafe {
            LLVMBuildRet(self.builder_ref, value.value_ref);
        }
    }

    pub fn store(&self, src: Value<'a>, dst: Value<'a>) {
        unsafe {
            LLVMBuildStore(self.builder_ref, src.value_ref, dst.value_ref);
        }
    }

    pub fn sub(&self, v1: Value<'a>, v2: Value<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildSub(self.builder_ref, v1.value_ref, v2.value_ref, name)
        })
    }

    pub fn trunc(&self, value: Value<'a>, ty: Type<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildTrunc(self.builder_ref, value.value_ref, ty.type_ref, name)
        })
    }

    pub fn zext(&self, value: Value<'a>, ty: Type<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildZExt(self.builder_ref, value.value_ref, ty.type_ref, name)
        })
    }
}
<commit_msg>No need to force linking against libffi.<commit_after>use std::ffi::{CString, CStr};
use std::os::raw::{c_char, c_uint};
use std::{mem, ptr};
use std::cell::RefCell;

use llvm_sys;
use llvm_sys::prelude::*;
use llvm_sys::core::*;
use llvm_sys::target;
use llvm_sys::analysis::{LLVMVerifyModule, LLVMVerifierFailureAction};
use llvm_sys::transforms::pass_manager_builder as builder;
use llvm_sys::execution_engine as engine;
pub use llvm_sys::LLVMIntPredicate;

pub struct Context {
    context_ref: LLVMContextRef,
    strings:     RefCell<Vec<CString>>,
}

impl Context {
    pub fn new() -> Self {
        Context {
            context_ref: unsafe { LLVMContextCreate() },
            strings:     RefCell::new(Vec::new()),
        }
    }

    pub fn new_name(&self, name: &str) -> *const c_char {
        let string = CString::new(name).unwrap();
        let ptr    = string.as_ptr();
        self.strings.borrow_mut().push(string);
        ptr
    }

    fn wrap_value(&self, value_ref: LLVMValueRef) -> Value {
        Value {
            value_ref: value_ref,
            context:   self,
        }
    }

    fn wrap_type(&self, type_ref: LLVMTypeRef) -> Type {
        Type {
            type_ref: type_ref,
            context:  self,
        }
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            LLVMContextDispose(self.context_ref);
        }
    }
}

#[derive(Clone, Copy)]
pub struct Module<'a> {
    module_ref: LLVMModuleRef,
    context:    &'a Context,
}

impl<'a> Module<'a> {
    pub fn new(context: &'a Context, name: &str) -> Self {
        let name = context.new_name(name);
        Module {
            module_ref: unsafe {
                LLVMModuleCreateWithNameInContext(name, context.context_ref)
            },
            context: context,
        }
    }

    pub fn add_function(&self, name: &str, ty: Type<'a>) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMAddFunction(self.module_ref, name, ty.type_ref)
        })
    }

    // From llvm-alt:
    pub fn optimize(&self, opt_level: usize, size_level: usize) {
        unsafe {
            let builder = builder::LLVMPassManagerBuilderCreate();
            builder::LLVMPassManagerBuilderSetOptLevel(builder, opt_level as _);
            builder::LLVMPassManagerBuilderSetSizeLevel(builder, size_level as _);
            let pass_manager = LLVMCreatePassManager();
            builder::LLVMPassManagerBuilderPopulateModulePassManager(builder, pass_manager);
            builder::LLVMPassManagerBuilderDispose(builder);
            LLVMRunPassManager(pass_manager, self.module_ref);
            LLVMDisposePassManager(pass_manager);
        }
    }

    pub fn dump(&self) {
        unsafe {
            LLVMDumpModule(self.module_ref);
        }
    }

    pub fn verify(&self) -> Result<(), String> {
        let mut out_message: *mut c_char = ptr::null_mut();

        unsafe {
            if LLVMVerifyModule(self.module_ref,
                                LLVMVerifierFailureAction::LLVMReturnStatusAction,
                                &mut out_message) == 0 {
                Ok(())
            } else {
                let result = CStr::from_ptr(out_message).to_string_lossy().into_owned();
                LLVMDisposeMessage(out_message);
                Err(result)
            }
        }
    }

    pub fn run_function(&self, name: &str) -> Result<u64, String> {
        let mut out_message: *mut c_char = ptr::null_mut();
        let mut exec: engine::LLVMExecutionEngineRef = ptr::null_mut();

        unsafe {
            engine::LLVMLinkInMCJIT();

            if target::LLVM_InitializeNativeAsmPrinter() == 1 {
                return Err("Could not initialize native asm printer for LLVM.".to_owned());
            }

            if target::LLVM_InitializeNativeTarget() == 1 {
                return Err("Could not initialize native target for LLVM.".to_owned());
            }

            let mut options = engine::LLVMMCJITCompilerOptions {
                OptLevel: 3,
                CodeModel: llvm_sys::target_machine::LLVMCodeModel::LLVMCodeModelDefault,
                NoFramePointerElim: 0,
                EnableFastISel: 0,
                MCJMM: ptr::null_mut(),
            };

            if engine::LLVMCreateMCJITCompilerForModule(
                &mut exec, self.module_ref,
                &mut options,
                mem::size_of::<c_uint>() as _,
                &mut out_message
            ) != 0 {
                let result = CStr::from_ptr(out_message).to_string_lossy().into_owned();
                LLVMDisposeMessage(out_message);
                return Err(result);
            }

            let cname    = CString::new(name).unwrap();
            let fun_addr = engine::LLVMGetFunctionAddress(exec, cname.as_ptr());
            let fun: extern fn() -> u64 = mem::transmute(fun_addr);

            Ok(fun())
        }
    }
}

#[derive(Copy, Clone)]
pub struct Type<'a> {
    type_ref:  LLVMTypeRef,
    context:   &'a Context,
}

impl<'a> Type<'a> {
    pub fn get_i64(context: &'a Context) -> Self {
        context.wrap_type(unsafe {
            LLVMInt64TypeInContext(context.context_ref)
        })
    }

    pub fn get_i32(context: &'a Context) -> Self {
        context.wrap_type(unsafe {
            LLVMInt32TypeInContext(context.context_ref)
        })
    }

    pub fn get_i8(context: &'a Context) -> Self {
        context.wrap_type(unsafe {
            LLVMInt8TypeInContext(context.context_ref)
        })
    }

    pub fn get_bool(context: &'a Context) -> Self {
        context.wrap_type(unsafe {
            LLVMInt1TypeInContext(context.context_ref)
        })
    }

    pub fn get_void(context: &'a Context) -> Self {
        context.wrap_type(unsafe {
            LLVMVoidTypeInContext(context.context_ref)
        })
    }

    pub fn get_pointer(target: Type<'a>) -> Self {
        target.context.wrap_type(unsafe {
            LLVMPointerType(target.type_ref, 0)
        })
    }

    pub fn get_function(args: &[Type<'a>], result: Type<'a>) -> Self {
        let mut args = args.into_iter().map(|arg| arg.type_ref).collect::<Vec<_>>();
        result.context.wrap_type(unsafe {
            LLVMFunctionType(result.type_ref,
                             args.as_mut_ptr(),
                             args.len() as _,
                             0)
        })
    }
}

#[derive(Copy, Clone)]
pub struct Value<'a> {
    value_ref: LLVMValueRef,
    context:   &'a Context,
}

impl<'a> Value<'a> {
//    pub fn get_fun_param(&self, index: usize) -> Self {
//        self.context.wrap_value(unsafe {
//            LLVMGetParam(self.value_ref, index as _)
//        })
//    }

    pub fn append(&self, name: &str) -> BasicBlock<'a> {
        let name = self.context.new_name(name);
        let bb_ref = unsafe {
            LLVMAppendBasicBlockInContext(self.context.context_ref,
                                          self.value_ref,
                                          name)
        };
        BasicBlock {
            bb_ref: bb_ref,
            _context: self.context,
        }
    }

    pub fn get_u64(context: &'a Context, value: u64) -> Self {
        context.wrap_value(unsafe {
            LLVMConstInt(Type::get_i64(context).type_ref,
                         value as _,
                         false as _)
        })
    }

    pub fn get_u32(context: &'a Context, value: u32) -> Self {
        context.wrap_value(unsafe {
            LLVMConstInt(Type::get_i32(context).type_ref,
                         value as _,
                         false as _)
        })
    }

    pub fn get_u8(context: &'a Context, value: u8) -> Self {
        context.wrap_value(unsafe {
            LLVMConstInt(Type::get_i8(context).type_ref,
                         value as _,
                         false as _)
        })
    }

    pub fn get_bool(context: &'a Context, value: bool) -> Self {
        context.wrap_value(unsafe {
            LLVMConstInt(Type::get_bool(context).type_ref,
                         value as _,
                         false as _)
        })
    }
}

#[derive(Copy, Clone)]
pub struct BasicBlock<'a> {
    bb_ref:  LLVMBasicBlockRef,
    _context: &'a Context,
}

#[derive(Copy, Clone)]
pub struct Builder<'a> {
    builder_ref: LLVMBuilderRef,
    context:     &'a Context,
}

impl<'a> Builder<'a> {
    pub fn new(context: &'a Context) -> Self {
        Builder {
            builder_ref: unsafe { LLVMCreateBuilderInContext(context.context_ref) },
            context:     context,
        }
    }

    pub fn position_at_end(&self, bb: BasicBlock<'a>) {
        unsafe {
            LLVMPositionBuilderAtEnd(self.builder_ref, bb.bb_ref);
        }
    }

    pub fn add(&self, v1: Value<'a>, v2: Value<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildAdd(self.builder_ref, v1.value_ref, v2.value_ref, name)
        })
    }

    pub fn alloca(&self, ty: Type<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildAlloca(self.builder_ref, ty.type_ref, name)
        })
    }

    pub fn array_alloca(&self, ty: Type<'a>, size: Value<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildArrayAlloca(self.builder_ref,
                                 ty.type_ref,
                                 size.value_ref,
                                 name)
        })
    }

    pub fn br(&self, dst: BasicBlock<'a>) {
        unsafe {
            LLVMBuildBr(self.builder_ref, dst.bb_ref);
        }
    }

    pub fn call(&self, fun: Value<'a>, args: &[Value<'a>], name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        let mut args = args.into_iter().map(|arg| arg.value_ref).collect::<Vec<_>>();
        self.context.wrap_value(unsafe {
            LLVMBuildCall(self.builder_ref,
                          fun.value_ref,
                          args.as_mut_ptr(),
                          args.len() as u32,
                          name)
        })
    }

    pub fn cmp(&self, pred: LLVMIntPredicate, lhs: Value<'a>, rhs: Value<'a>,
               name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildICmp(self.builder_ref, pred, lhs.value_ref, rhs.value_ref, name)

        })
    }

    pub fn cond_br(&self, test: Value<'a>, then: BasicBlock<'a>, else_: BasicBlock<'a>) {
        unsafe {
            LLVMBuildCondBr(self.builder_ref, test.value_ref, then.bb_ref, else_.bb_ref);
        }
    }

    pub fn gep(&self, ptr: Value<'a>, indices: &[Value<'a>], name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        let mut indices = indices.into_iter().map(|i| i.value_ref).collect::<Vec<_>>();
        self.context.wrap_value(unsafe {
            LLVMBuildGEP(self.builder_ref,
                         ptr.value_ref,
                         indices.as_mut_ptr(),
                         indices.len() as u32,
                         name)
        })
    }

    pub fn load(&self, ptr: Value<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildLoad(self.builder_ref, ptr.value_ref, name)
        })
    }

    pub fn ret(&self, value: Value<'a>) {
        unsafe {
            LLVMBuildRet(self.builder_ref, value.value_ref);
        }
    }

    pub fn store(&self, src: Value<'a>, dst: Value<'a>) {
        unsafe {
            LLVMBuildStore(self.builder_ref, src.value_ref, dst.value_ref);
        }
    }

    pub fn sub(&self, v1: Value<'a>, v2: Value<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildSub(self.builder_ref, v1.value_ref, v2.value_ref, name)
        })
    }

    pub fn trunc(&self, value: Value<'a>, ty: Type<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildTrunc(self.builder_ref, value.value_ref, ty.type_ref, name)
        })
    }

    pub fn zext(&self, value: Value<'a>, ty: Type<'a>, name: &str) -> Value<'a> {
        let name = self.context.new_name(name);
        self.context.wrap_value(unsafe {
            LLVMBuildZExt(self.builder_ref, value.value_ref, ty.type_ref, name)
        })
    }
}
<|endoftext|>


<commit_before>use core::*;

/// A player
pub struct Player {
  pos: Vec2<i64>,
  dir: Dir,
  trans: f64,
  frame: i16,
  last_move: f64,
}

impl Positioned for Player {
  fn get_pos(&self) -> Vec2<i64> {
    self.pos
  }
  fn set_pos(&mut self, new_pos: Vec2<i64>) {
    self.pos = new_pos;
  }
}

impl Movable for Player {
  fn get_dir(&self) -> Dir {
    self.dir
  }
  fn set_dir(&mut self, new_dir: Dir) {
    self.dir = new_dir;
  }
  fn is_moving(&self) -> bool {
    // TODO: Code here.
    true
  }
}

impl Animated for Player {
  fn get_trans_state(&self) -> f64 {
    self.trans
  }
  fn get_animation_frame(&self) -> i16 {
    self.frame
  }
}

impl Sprited for Player {
  fn get_sprite(&self) -> &Texture {
    unimplemented!();
    // TODO: Sprite here
  }
  fn get_width(&self) -> i16 {
    1
  }
  fn get_height(&self) -> i16 {
    1
  }
  fn get_opacity(&self) -> f64 {
    1.0
  }
}

impl Entity for Player {
  fn id(&self) -> Id {
    Id(0) // NOTE: Player's ID is always 0
  }
  fn is_solid(&self, x: i16, y: i16) -> bool {
    false // TODO: Should it be solid?
  }
  fn update(&mut self, dt: f64) {
    // TODO: Following shall be integrated in core (last move)
    if self.is_moving() && self.last_move > 1.0 {
      self.move_obj_dir()
    } else {
      self.last_move += dt;
    }
  }
}
<commit_msg>Add speeds and better movement<commit_after>use core::*;

/// A player
pub struct Player {
  pos: Vec2<i64>,
  dir: Dir,
  trans: f64,
  frame: i16,
  last_move: f64,
}

impl Positioned for Player {
  fn get_pos(&self) -> Vec2<i64> {
    self.pos
  }
  fn set_pos(&mut self, new_pos: Vec2<i64>) {
    self.pos = new_pos;
  }
}

impl Movable for Player {
  fn get_dir(&self) -> Dir {
    self.dir
  }
  fn set_dir(&mut self, new_dir: Dir) {
    self.dir = new_dir;
  }
  fn is_moving(&self) -> bool {
    // TODO: Code here.
    true
  }
  fn get_last_move(&self) -> f64 {
    self.last_move
  }
  fn set_last_move(&mut self, new: &f64) {
    self.last_move = *new;
  }
  fn get_speed(&self) -> f64 {
    1.0
  }
}

impl Animated for Player {
  fn get_trans_state(&self) -> f64 {
    self.trans
  }
  fn get_animation_frame(&self) -> i16 {
    self.frame
  }
}

impl Sprited for Player {
  fn get_sprite(&self) -> &Texture {
    unimplemented!();
    // TODO: Sprite here
  }
  fn get_width(&self) -> i16 {
    1
  }
  fn get_height(&self) -> i16 {
    1
  }
  fn get_opacity(&self) -> f64 {
    1.0
  }
}

impl Entity for Player {
  fn id(&self) -> Id {
    Id(0) // NOTE: Player's ID is always 0
  }
  fn is_solid(&self, x: i16, y: i16) -> bool {
    false // TODO: Should it be solid?
  }
  fn update(&mut self, dt: f64) {
    self.move_reg();
  }
}
<|endoftext|>


<commit_before>// use std::collections::HashMap;
use std::ffi::CString;
use libc::c_int;

use super::ffi;

use {SqliteResult, SqliteError, SqliteConnection, SqliteStatement, SqliteRows, SqliteRow};
use types::ToSql;

impl SqliteConnection {
    /// Convenience method to prepare and execute a single SQL statement with named parameter(s).
    ///
    /// ## Example
    ///
    /// ```rust,no_run
    /// # use rusqlite::{SqliteConnection, SqliteResult};
    /// fn insert(conn: &SqliteConnection) -> SqliteResult<i32> {
    ///   conn.execute_named("INSERT INTO test (id, name, flag) VALUES (:id, :name, :flag)", &[(":name", &"one")])
    /// }
    /// ```
    ///
    /// # Failure
    ///
    /// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the
    /// underlying SQLite call fails.
    pub fn execute_named(&self, sql: &str, params: &[(&str, &ToSql)]) -> SqliteResult<c_int> {
        self.prepare(sql).and_then(|mut stmt| stmt.execute_named(params))
    }

    /// Convenience method to execute a query with named parameter(s) that is expected to return a single row.
    ///
    /// If the query returns more than one row, all rows except the first are ignored.
    ///
    /// # Failure
    ///
    /// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the
    /// underlying SQLite call fails.
    pub fn query_named_row<T, F>(&self,
                                 sql: &str,
                                 params: &[(&str, &ToSql)],
                                 f: F)
                                 -> SqliteResult<T>
        where F: FnOnce(SqliteRow) -> T
    {
        let mut stmt = try!(self.prepare(sql));
        let mut rows = try!(stmt.query_named(params));

        match rows.next() {
            Some(row) => row.map(f),
            None => {
                Err(SqliteError {
                    code: ffi::SQLITE_NOTICE,
                    message: "Query did not return a row".to_string(),
                })
            }
        }
    }
}

impl<'conn> SqliteStatement<'conn> {
    // pub fn parameter_names(&self) -> HashMap<String, i32> {
    // let n = unsafe { ffi::sqlite3_bind_parameter_count(self.stmt) };
    // let mut index_by_name = HashMap::with_capacity(n as usize);
    // for i in 1..n+1 {
    // let c_name = unsafe { ffi::sqlite3_bind_parameter_name(self.stmt, i) };
    // if !c_name.is_null() {
    // let c_slice = unsafe { CStr::from_ptr(c_name).to_bytes() };
    // index_by_name.insert(str::from_utf8(c_slice).unwrap().to_string(), n);
    // }
    // }
    // index_by_name
    // }

    /// Return the index of an SQL parameter given its name.
    ///
    /// # Failure
    ///
    /// Return None if `name` is invalid (NulError) or if no matching parameter is found.
    pub fn parameter_index(&self, name: &str) -> Option<i32> {
        unsafe {
            CString::new(name).ok().and_then(|c_name| {
                match ffi::sqlite3_bind_parameter_index(self.stmt, c_name.as_ptr()) {
                    0 => None, // A zero is returned if no matching parameter is found.
                    n => Some(n),
                }
            })

        }
    }

    /// Execute the prepared statement with named parameter(s).
    ///
    /// On success, returns the number of rows that were changed or inserted or deleted (via
    /// `sqlite3_changes`).
    ///
    /// ## Example
    ///
    /// ```rust,no_run
    /// # use rusqlite::{SqliteConnection, SqliteResult};
    /// fn insert(conn: &SqliteConnection) -> SqliteResult<i32> {
    ///   let mut stmt = try!(conn.prepare("INSERT INTO test (id, name, flag) VALUES (:id, :name, :flag)"));
    ///   return stmt.execute_named(&[(":name", &"one")]);
    /// }
    /// ```
    ///
    /// # Failure
    ///
    /// Will return `Err` if binding parameters fails, the executed statement returns rows (in
    /// which case `query` should be used instead), or the underling SQLite call fails.
    pub fn execute_named(&mut self, params: &[(&str, &ToSql)]) -> SqliteResult<c_int> {
        unsafe {
            try!(self.bind_named_parameters(params));
            self.execute_()
        }
    }

    /// Execute the prepared statement with named parameter(s), returning an iterator over the resulting rows.
    ///
    /// ## Example
    ///
    /// ```rust,no_run
    /// # use rusqlite::{SqliteConnection, SqliteResult, SqliteRows};
    /// fn query(conn: &SqliteConnection) -> SqliteResult<()> {
    ///   let mut stmt = try!(conn.prepare("SELECT * FROM test where name = :name"));
    ///   let mut rows = try!(stmt.query_named(&[(":name", &"one")]));
    ///   for row in rows {
    ///   // ...
    ///   }
    ///   return Ok(())
    /// }
    /// ```
    ///
    /// # Failure
    ///
    /// Will return `Err` if binding parameters fails.
    pub fn query_named<'a>(&'a mut self,
                           params: &[(&str, &ToSql)])
                           -> SqliteResult<SqliteRows<'a>> {
        self.reset_if_needed();

        unsafe {
            try!(self.bind_named_parameters(params));
        }

        self.needs_reset = true;
        Ok(SqliteRows::new(self))
    }

    unsafe fn bind_named_parameters(&mut self, params: &[(&str, &ToSql)]) -> SqliteResult<()> {
        // Always check that the number of parameters is correct.
        assert!(params.len() as c_int == ffi::sqlite3_bind_parameter_count(self.stmt),
                "incorrect number of parameters to query(): expected {}, got {}",
                ffi::sqlite3_bind_parameter_count(self.stmt),
                params.len());

        // In debug, also sanity check that we got distinct parameter names.
        debug_assert!({
                          use std::collections::HashSet;

                          let mut s = HashSet::with_capacity(params.len());
                          for &(name, _) in params {
                              s.insert(name);
                          }

                          s.len() == params.len()
                      },
                      "named parameters must be unique");

        for &(name, value) in params {
            let i = try!(self.parameter_index(name).ok_or(SqliteError {
                code: ffi::SQLITE_MISUSE,
                message: format!("Invalid parameter name: {}", name),
            }));
            try!(self.conn.decode_result(value.bind_parameter(self.stmt, i)));
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use SqliteConnection;

    #[test]
    fn test_execute_named() {
        let db = SqliteConnection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo(x INTEGER)").unwrap();

        assert_eq!(db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &1i32)]).unwrap(),
                   1);
        assert_eq!(db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &2i32)]).unwrap(),
                   1);

        assert_eq!(3i32,
                   db.query_named_row("SELECT SUM(x) FROM foo WHERE x > :x",
                                      &[(":x", &0i32)],
                                      |r| r.get(0))
                     .unwrap());
    }

    #[test]
    fn test_stmt_execute_named() {
        let db = SqliteConnection::open_in_memory().unwrap();
        let sql = "CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag \
                   INTEGER)";
        db.execute_batch(sql).unwrap();

        let mut stmt = db.prepare("INSERT INTO test (name) VALUES (:name)").unwrap();
        stmt.execute_named(&[(":name", &"one")]).unwrap();

        assert_eq!(1i32,
                   db.query_named_row("SELECT COUNT(*) FROM test WHERE name = :name",
                                      &[(":name", &"one")],
                                      |r| r.get(0))
                     .unwrap());
    }

    #[test]
    fn test_query_named() {
        let db = SqliteConnection::open_in_memory().unwrap();
        let sql = "CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag \
                   INTEGER)";
        db.execute_batch(sql).unwrap();

        let mut stmt = db.prepare("SELECT * FROM test where name = :name").unwrap();
        stmt.query_named(&[(":name", &"one")]).unwrap();
    }

    #[test]
    #[should_panic]
    fn test_panic_on_incorrect_number_of_parameters() {
        let db = SqliteConnection::open_in_memory().unwrap();

        let mut stmt = db.prepare("SELECT 1 WHERE 1 = :one AND 2 = :two").unwrap();
        let _ = stmt.query_named(&[(":one", &1i32)]);
    }

    #[test]
    #[cfg(debug_assertions)]
    #[should_panic]
    fn test_debug_panic_on_incorrect_parameter_names() {
        let db = SqliteConnection::open_in_memory().unwrap();

        let mut stmt = db.prepare("SELECT 1 WHERE 1 = :one AND 2 = :two").unwrap();
        let _ = stmt.query_named(&[(":one", &1i32), (":one", &2i32)]);
    }
}
<commit_msg>Clean up comments on named parameter methods<commit_after>// use std::collections::HashMap;
use std::ffi::CString;
use libc::c_int;

use super::ffi;

use {SqliteResult, SqliteError, SqliteConnection, SqliteStatement, SqliteRows, SqliteRow};
use types::ToSql;

impl SqliteConnection {
    /// Convenience method to prepare and execute a single SQL statement with named parameter(s).
    ///
    /// On success, returns the number of rows that were changed or inserted or deleted (via
    /// `sqlite3_changes`).
    ///
    /// ## Example
    ///
    /// ```rust,no_run
    /// # use rusqlite::{SqliteConnection, SqliteResult};
    /// fn insert(conn: &SqliteConnection) -> SqliteResult<i32> {
    ///     conn.execute_named("INSERT INTO test (name) VALUES (:name)", &[(":name", &"one")])
    /// }
    /// ```
    ///
    /// # Failure
    ///
    /// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the
    /// underlying SQLite call fails.
    pub fn execute_named(&self, sql: &str, params: &[(&str, &ToSql)]) -> SqliteResult<c_int> {
        self.prepare(sql).and_then(|mut stmt| stmt.execute_named(params))
    }

    /// Convenience method to execute a query with named parameter(s) that is expected to return
    /// a single row.
    ///
    /// If the query returns more than one row, all rows except the first are ignored.
    ///
    /// # Failure
    ///
    /// Will return `Err` if `sql` cannot be converted to a C-compatible string or if the
    /// underlying SQLite call fails.
    pub fn query_named_row<T, F>(&self,
                                 sql: &str,
                                 params: &[(&str, &ToSql)],
                                 f: F)
                                 -> SqliteResult<T>
        where F: FnOnce(SqliteRow) -> T
    {
        let mut stmt = try!(self.prepare(sql));
        let mut rows = try!(stmt.query_named(params));

        match rows.next() {
            Some(row) => row.map(f),
            None => {
                Err(SqliteError {
                    code: ffi::SQLITE_NOTICE,
                    message: "Query did not return a row".to_string(),
                })
            }
        }
    }
}

impl<'conn> SqliteStatement<'conn> {
    // pub fn parameter_names(&self) -> HashMap<String, i32> {
    // let n = unsafe { ffi::sqlite3_bind_parameter_count(self.stmt) };
    // let mut index_by_name = HashMap::with_capacity(n as usize);
    // for i in 1..n+1 {
    // let c_name = unsafe { ffi::sqlite3_bind_parameter_name(self.stmt, i) };
    // if !c_name.is_null() {
    // let c_slice = unsafe { CStr::from_ptr(c_name).to_bytes() };
    // index_by_name.insert(str::from_utf8(c_slice).unwrap().to_string(), n);
    // }
    // }
    // index_by_name
    // }

    /// Return the index of an SQL parameter given its name.
    ///
    /// # Failure
    ///
    /// Return None if `name` is invalid or if no matching parameter is found.
    pub fn parameter_index(&self, name: &str) -> Option<i32> {
        unsafe {
            CString::new(name).ok().and_then(|c_name| {
                match ffi::sqlite3_bind_parameter_index(self.stmt, c_name.as_ptr()) {
                    0 => None, // A zero is returned if no matching parameter is found.
                    n => Some(n),
                }
            })

        }
    }

    /// Execute the prepared statement with named parameter(s).
    ///
    /// On success, returns the number of rows that were changed or inserted or deleted (via
    /// `sqlite3_changes`).
    ///
    /// ## Example
    ///
    /// ```rust,no_run
    /// # use rusqlite::{SqliteConnection, SqliteResult};
    /// fn insert(conn: &SqliteConnection) -> SqliteResult<i32> {
    ///     let mut stmt = try!(conn.prepare("INSERT INTO test (name) VALUES (:name)"));
    ///     stmt.execute_named(&[(":name", &"one")])
    /// }
    /// ```
    ///
    /// # Failure
    ///
    /// Will return `Err` if binding parameters fails, the executed statement returns rows (in
    /// which case `query` should be used instead), or the underling SQLite call fails.
    pub fn execute_named(&mut self, params: &[(&str, &ToSql)]) -> SqliteResult<c_int> {
        unsafe {
            try!(self.bind_named_parameters(params));
            self.execute_()
        }
    }

    /// Execute the prepared statement with named parameter(s), returning an iterator over the
    /// resulting rows.
    ///
    /// ## Example
    ///
    /// ```rust,no_run
    /// # use rusqlite::{SqliteConnection, SqliteResult, SqliteRows};
    /// fn query(conn: &SqliteConnection) -> SqliteResult<()> {
    ///     let mut stmt = try!(conn.prepare("SELECT * FROM test where name = :name"));
    ///     let mut rows = try!(stmt.query_named(&[(":name", &"one")]));
    ///     for row in rows {
    ///         // ...
    ///     }
    ///     Ok(())
    /// }
    /// ```
    ///
    /// # Failure
    ///
    /// Will return `Err` if binding parameters fails.
    pub fn query_named<'a>(&'a mut self,
                           params: &[(&str, &ToSql)])
                           -> SqliteResult<SqliteRows<'a>> {
        self.reset_if_needed();

        unsafe {
            try!(self.bind_named_parameters(params));
        }

        self.needs_reset = true;
        Ok(SqliteRows::new(self))
    }

    unsafe fn bind_named_parameters(&mut self, params: &[(&str, &ToSql)]) -> SqliteResult<()> {
        // Always check that the number of parameters is correct.
        assert!(params.len() as c_int == ffi::sqlite3_bind_parameter_count(self.stmt),
                "incorrect number of parameters to query(): expected {}, got {}",
                ffi::sqlite3_bind_parameter_count(self.stmt),
                params.len());

        // In debug, also sanity check that we got distinct parameter names.
        debug_assert!({
                          use std::collections::HashSet;

                          let mut s = HashSet::with_capacity(params.len());
                          for &(name, _) in params {
                              s.insert(name);
                          }

                          s.len() == params.len()
                      },
                      "named parameters must be unique");

        for &(name, value) in params {
            let i = try!(self.parameter_index(name).ok_or(SqliteError {
                code: ffi::SQLITE_MISUSE,
                message: format!("Invalid parameter name: {}", name),
            }));
            try!(self.conn.decode_result(value.bind_parameter(self.stmt, i)));
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use SqliteConnection;

    #[test]
    fn test_execute_named() {
        let db = SqliteConnection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo(x INTEGER)").unwrap();

        assert_eq!(db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &1i32)]).unwrap(),
                   1);
        assert_eq!(db.execute_named("INSERT INTO foo(x) VALUES (:x)", &[(":x", &2i32)]).unwrap(),
                   1);

        assert_eq!(3i32,
                   db.query_named_row("SELECT SUM(x) FROM foo WHERE x > :x",
                                      &[(":x", &0i32)],
                                      |r| r.get(0))
                     .unwrap());
    }

    #[test]
    fn test_stmt_execute_named() {
        let db = SqliteConnection::open_in_memory().unwrap();
        let sql = "CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag \
                   INTEGER)";
        db.execute_batch(sql).unwrap();

        let mut stmt = db.prepare("INSERT INTO test (name) VALUES (:name)").unwrap();
        stmt.execute_named(&[(":name", &"one")]).unwrap();

        assert_eq!(1i32,
                   db.query_named_row("SELECT COUNT(*) FROM test WHERE name = :name",
                                      &[(":name", &"one")],
                                      |r| r.get(0))
                     .unwrap());
    }

    #[test]
    fn test_query_named() {
        let db = SqliteConnection::open_in_memory().unwrap();
        let sql = "CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, name TEXT NOT NULL, flag \
                   INTEGER)";
        db.execute_batch(sql).unwrap();

        let mut stmt = db.prepare("SELECT * FROM test where name = :name").unwrap();
        stmt.query_named(&[(":name", &"one")]).unwrap();
    }

    #[test]
    #[should_panic]
    fn test_panic_on_incorrect_number_of_parameters() {
        let db = SqliteConnection::open_in_memory().unwrap();

        let mut stmt = db.prepare("SELECT 1 WHERE 1 = :one AND 2 = :two").unwrap();
        let _ = stmt.query_named(&[(":one", &1i32)]);
    }

    #[test]
    #[cfg(debug_assertions)]
    #[should_panic]
    fn test_debug_panic_on_incorrect_parameter_names() {
        let db = SqliteConnection::open_in_memory().unwrap();

        let mut stmt = db.prepare("SELECT 1 WHERE 1 = :one AND 2 = :two").unwrap();
        let _ = stmt.query_named(&[(":one", &1i32), (":one", &2i32)]);
    }
}
<|endoftext|>


<commit_before>
use std::comm::{Chan, Port, SharedChan};

use std::hashmap::{HashMap};

use std::task::{task};

pub enum ObjectBrokerMessage {

	// ## Object management ##

	// request from thread a to addref object b
	// if the object is not known to the broker yet,
	// this registers the object for as pertaining
	// to thread a.
	OB_RQ_ADD_REF(uint, uint),

	// request from thread a to release object b
	// if thread a owns this object, the message informs
	// the broker that the object has been deleted.
	OB_RQ_RELEASE(uint, uint),

	// thread a asks which thread owns object b
	// response is the same message with a (c, b) tuple,
	// c is the id of the the owning thread.
	OB_RQ_WHO_OWNS(uint, uint),

	// thread a asks to take over ownership of object b
	OB_RQ_OWN(uint, uint),

	// thread a abandons ownership of object b
	// when send from broker to a thread c, this means that this
	// thread should take over ownership of the object. When
	// send from a thread to broker in response to a RQ_OWN
	// message, the last tuple element indicates the original
	// asker.
	OB_RQ_DISOWN(uint, uint, ~[u8], uint),

	// ## Thread management ##

	// a new thread a registers with the object broker
	OB_REGISTER(uint, Chan<ObjectBrokerMessage>),

	// ## VM management ##
	OB_SHUTDOWN
}

// The ObjectBroker handles ownership for concurrently accessed
// objects. At every time, an object has one well-defined owner.
// If a thread needs access to an object that it does not currently
// own, it submits a OB_RQ_OWN message to the object broker, which
// in turn asks the thread who owns the object to relinquish it using
// a OB_RQ_DISOWN message. The owning thread gives up ownership and
// sends a OB_RQ_DISOWN message to the broker, which forwards it to
// the original thread and updates its book-keeping to reflect the
// change in ownership.
//
// The ObjectBroker keeps a HM of object ids mapped to their owning
// thread ids.
//
// When a thread dies, it forwards all of its alive objects to the
// object broker using a OB_OUT_RE_OBJ message. The broker, in turn,
// keeps those objects internally until another thread demands to
// own them.
pub struct ObjectBroker {
	objects_with_owners: HashMap<uint, uint>,

	in_port : Port<ObjectBrokerMessage>,
	out_chan : HashMap<uint, Chan<ObjectBrokerMessage>>,

	// this is duplicated into all
	in_shared_chan : SharedChan<ObjectBrokerMessage>,
}

static OB_INITIAL_OBJ_HASHMAP_CAPACITY : uint = 4096;
static OB_INITIAL_THREAD_CAPACITY : uint = 16;

impl ObjectBroker {

	// ----------------------------------------------
	pub fn new() -> ObjectBroker
	{
	 	let (out,input) = SharedChan::new();
		ObjectBroker {
			objects_with_owners : HashMap::with_capacity(OB_INITIAL_OBJ_HASHMAP_CAPACITY),

			in_port : out,
			in_shared_chan : input,
			out_chan : HashMap::with_capacity(OB_INITIAL_THREAD_CAPACITY),
		}
	}

	// ----------------------------------------------
	// Launches the object broker. Returns a SharedChan object that can be used
	// to direct messages to the broker. Send an OB_SHUTDOWN to terminate
	// operation.
	pub fn launch(mut self) -> SharedChan<ObjectBrokerMessage> {
		let ret_chan = self.in_shared_chan.clone();
		do spawn {
			self.task_main();
		}
		return ret_chan;
	}

	// IMPL

	// ----------------------------------------------
	fn task_main(mut self) {
		let ref mut objects = self.objects_with_owners;
		let ref mut threads = self.out_chan;

		loop {
			match self.in_port.recv() {
				OB_RQ_ADD_REF(a,b) => {
					// for somebody to have a reference to a field and thus
					// being able to addref/release it, they must have had
					// accss to an object that was owned by this thread.
					// As this object must have been transferred using the
					// object broker and messages are guaranteed to be
					// ordered, we must already know about that object.

					// Therefore, whether the object is present in the HM
					// is safe for determining whether it is new.
					match objects.find(&b) {
						Some(owner) => {
							let t = threads.get(owner);
							t.send(OB_RQ_ADD_REF(a,b));
							continue;
						},
						_ => (),
					}
					objects.insert(b,a);
				}

				OB_RQ_RELEASE(a,b) => {
					// correctness follows by the same reasoning as for AddRef()
					let owner = *objects.get(&b);
					if owner == a {
						objects.remove(&b);
					}
					else {
						let t = threads.get(&owner);
						t.send(OB_RQ_RELEASE(a,b));
					}
				},

				OB_RQ_WHO_OWNS(a,b) => {
					let t = threads.get(&a);
					t.send(OB_RQ_WHO_OWNS(*objects.get(&b),b));
				},

				OB_RQ_OWN(a,b) => {
					// b must be in objects as per the same reasoning as
					// OB_RQ_ADD_REF() is sound.

					let owner = *objects.get(&b);
					// cannot request object oned by oneself
					// bookkeeping of own owned objects is consistent,
					// so failure to hold this would be a logic error.
					assert!(owner != a);

					// TODO: what if somebody else concurrently requested
					// owning the object, but has not received it yet?

					let t = threads.get(&owner);
					t.send(OB_RQ_OWN(a, b));
				},

				OB_RQ_DISOWN(a,b,obj,receiver) => {
					// must own object to be able to disown it
					assert!(*objects.get(&b) == a);

					*objects.get_mut(&b) = receiver;
					let t = threads.get(&receiver);
					t.send(OB_RQ_DISOWN(a, b, obj, receiver));
				},

				OB_REGISTER(a, chan) => {
					assert!(!threads.contains_key(&a));
					threads.insert(a, chan);
					debug!("object broker registered with thread {}", a);
				},

				OB_SHUTDOWN => {
					debug!("object broker shutting down");
					break;
				},
			}
		}
	}
}

#[cfg(test)]
mod tests {
	use objectbroker::*;
	use std::task::{task};

	type test_proc = proc(SharedChan<ObjectBrokerMessage>, Port<ObjectBrokerMessage>) -> ();

	fn test_setup(a : test_proc, b : test_proc) {
		let mut ob = ObjectBroker::new();
		let chan = ob.launch();

		// thread 1
		let input1 = chan.clone();
		let mut t1 = task();
		let f1 = t1.future_result();
		do t1.spawn {
			let (port, chan) = Chan::new();
			input1.send(OB_REGISTER(1, chan));

			a(input1, port);
		}

		// thread 2
		let input2 = chan.clone();
		let mut t2 = task();
		let f2 = t2.future_result();
		do t2.spawn {
			let (port, chan) = Chan::new();
			input2.send(OB_REGISTER(2, chan));

			b(input2, port);
		}

		f1.recv();
		f2.recv();
	}

	#[test]
	fn test_object_broker() {
		let (sync_port, sync_chan) = Chan::new();
		test_setup(
			proc(input : SharedChan<ObjectBrokerMessage>, output: Port<ObjectBrokerMessage>) {
				// register object 15
				input.send(OB_RQ_ADD_REF(1,15));
				sync_chan.send(1);

				let request = output.recv();
				match request {
					OB_RQ_OWN(2,15) => input.send(OB_RQ_DISOWN(1,15,~[0x12 as u8],2)),
					_ => assert!(false),
				}
			},
			proc(input : SharedChan<ObjectBrokerMessage>, output: Port<ObjectBrokerMessage>) {
				// we have to ensure that object 15 is registered. Normally,
				// this is implicitly guaranteed because how would we otherwise
				// know about its id?
				sync_port.recv();

				// want to own object 15
				input.send(OB_RQ_OWN(2,15));

				let response = output.recv();
				match response {
					OB_RQ_DISOWN(1,15,val,2) => {
						assert_eq!(val[0], 0x12 as u8);
						input.send(OB_SHUTDOWN);
					},
					_ => assert!(false),
				}
			}
		);
	}
}

// TODO: tests of more complex scenarios
<commit_msg>objectbroker: further refactoring<commit_after>
use std::comm::{Chan, Port, SharedChan};

use std::hashmap::{HashMap};

use std::task::{task};

pub enum ObjectBrokerMessage {

	// ## Object management ##

	// request from thread a to addref object b
	// if the object is not known to the broker yet,
	// this registers the object for as pertaining
	// to thread a.
	OB_RQ_ADD_REF(uint, uint),

	// request from thread a to release object b
	// if thread a owns this object, the message informs
	// the broker that the object has been deleted.
	OB_RQ_RELEASE(uint, uint),

	// thread a asks which thread owns object b
	// response is the same message with a (c, b) tuple,
	// c is the id of the the owning thread.
	OB_RQ_WHO_OWNS(uint, uint),

	// thread a asks to take over ownership of object b
	OB_RQ_OWN(uint, uint),

	// thread a abandons ownership of object b
	// when send from broker to a thread c, this means that this
	// thread should take over ownership of the object. When
	// send from a thread to broker in response to a RQ_OWN
	// message, the last tuple element indicates the original
	// asker.
	OB_RQ_DISOWN(uint, uint, ~[u8], uint),

	// ## Thread management ##

	// a new thread a registers with the object broker
	OB_REGISTER(uint, Chan<ObjectBrokerMessage>),

	// ## VM management ##
	OB_SHUTDOWN
}

// The ObjectBroker handles ownership for concurrently accessed
// objects. At every time, an object has one well-defined owner.
// If a thread needs access to an object that it does not currently
// own, it submits a OB_RQ_OWN message to the object broker, which
// in turn asks the thread who owns the object to relinquish it using
// a OB_RQ_DISOWN message. The owning thread gives up ownership and
// sends a OB_RQ_DISOWN message to the broker, which forwards it to
// the original thread and updates its book-keeping to reflect the
// change in ownership.
//
// The ObjectBroker keeps a HM of object ids mapped to their owning
// thread ids.
//
// When a thread dies, it forwards all of its alive objects to the
// object broker using a OB_OUT_RE_OBJ message. The broker, in turn,
// keeps those objects internally until another thread demands to
// own them.
pub struct ObjectBroker {
	objects_with_owners: HashMap<uint, uint>,

	in_port : Port<ObjectBrokerMessage>,
	out_chan : HashMap<uint, Chan<ObjectBrokerMessage>>,

	// this is duplicated into all
	in_shared_chan : SharedChan<ObjectBrokerMessage>,
}

static OB_INITIAL_OBJ_HASHMAP_CAPACITY : uint = 4096;
static OB_INITIAL_THREAD_CAPACITY : uint = 16;

impl ObjectBroker {

	// ----------------------------------------------
	pub fn new() -> ObjectBroker
	{
	 	let (out,input) = SharedChan::new();
		ObjectBroker {
			objects_with_owners : HashMap::with_capacity(OB_INITIAL_OBJ_HASHMAP_CAPACITY),

			in_port : out,
			in_shared_chan : input,
			out_chan : HashMap::with_capacity(OB_INITIAL_THREAD_CAPACITY),
		}
	}

	// ----------------------------------------------
	// Launches the object broker. Returns a SharedChan object that can be used
	// to direct messages to the broker. Send an OB_SHUTDOWN to terminate
	// operation.
	pub fn launch(mut self) -> SharedChan<ObjectBrokerMessage> {
		let ret_chan = self.in_shared_chan.clone();

		// ownership of th ObjectBroker instance moves into the task,
		// all the caller gets back is a channel to communicate.
		do spawn {
			let mut s = self;
			while s.handle_message() {}
		}
		return ret_chan;
	}

	// IMPL

	// ----------------------------------------------
	fn handle_message(&mut self) -> bool {
		let ref mut objects = self.objects_with_owners;
		let ref mut threads = self.out_chan;

		match self.in_port.recv() {
			OB_RQ_ADD_REF(a,b) => {
				// for somebody to have a reference to a field and thus
				// being able to addref/release it, they must have had
				// accss to an object that was owned by this thread.
				// As this object must have been transferred using the
				// object broker and messages are guaranteed to be
				// ordered, we must already know about that object.

				// Therefore, whether the object is present in the HM
				// is safe for determining whether it is new.
				match objects.find(&b) {
					Some(owner) => {
						let t = threads.get(owner);
						t.send(OB_RQ_ADD_REF(a,b));
						return true;
					},
					_ => (),
				}
				objects.insert(b,a);
			}

			OB_RQ_RELEASE(a,b) => {
				// correctness follows by the same reasoning as for AddRef()
				let owner = *objects.get(&b);
				if owner == a {
					objects.remove(&b);
				}
				else {
					let t = threads.get(&owner);
					t.send(OB_RQ_RELEASE(a,b));
				}
			},

			OB_RQ_WHO_OWNS(a,b) => {
				let t = threads.get(&a);
				t.send(OB_RQ_WHO_OWNS(*objects.get(&b),b));
			},

			OB_RQ_OWN(a,b) => {
				// b must be in objects as per the same reasoning as
				// OB_RQ_ADD_REF() is sound.

				let owner = *objects.get(&b);
				// cannot request object oned by oneself
				// bookkeeping of own owned objects is consistent,
				// so failure to hold this would be a logic error.
				assert!(owner != a);

				// TODO: what if somebody else concurrently requested
				// owning the object, but has not received it yet?

				let t = threads.get(&owner);
				t.send(OB_RQ_OWN(a, b));
			},

			OB_RQ_DISOWN(a,b,obj,receiver) => {
				// must own object to be able to disown it
				assert!(*objects.get(&b) == a);

				*objects.get_mut(&b) = receiver;
				let t = threads.get(&receiver);
				t.send(OB_RQ_DISOWN(a, b, obj, receiver));
			},

			OB_REGISTER(a, chan) => {
				assert!(!threads.contains_key(&a));
				threads.insert(a, chan);
				debug!("object broker registered with thread {}", a);
			},

			OB_SHUTDOWN => {
				debug!("object broker shutting down");
				return false;
			},
		}
		return true;
	}
}

#[cfg(test)]
mod tests {
	use objectbroker::*;
	use std::task::{task};

	type test_proc = proc(SharedChan<ObjectBrokerMessage>, Port<ObjectBrokerMessage>) -> ();

	fn test_setup(a : test_proc, b : test_proc) {
		let mut ob = ObjectBroker::new();
		let chan = ob.launch();

		// thread 1
		let input1 = chan.clone();
		let mut t1 = task();
		let f1 = t1.future_result();
		do t1.spawn {
			let (port, chan) = Chan::new();
			input1.send(OB_REGISTER(1, chan));

			a(input1, port);
		}

		// thread 2
		let input2 = chan.clone();
		let mut t2 = task();
		let f2 = t2.future_result();
		do t2.spawn {
			let (port, chan) = Chan::new();
			input2.send(OB_REGISTER(2, chan));

			b(input2, port);
		}

		f1.recv();
		f2.recv();
	}

	#[test]
	fn test_object_broker() {
		let (sync_port, sync_chan) = Chan::new();
		test_setup(
			proc(input : SharedChan<ObjectBrokerMessage>, output: Port<ObjectBrokerMessage>) {
				// register object 15
				input.send(OB_RQ_ADD_REF(1,15));
				sync_chan.send(1);

				let request = output.recv();
				match request {
					OB_RQ_OWN(2,15) => input.send(OB_RQ_DISOWN(1,15,~[0x12 as u8],2)),
					_ => assert!(false),
				}
			},
			proc(input : SharedChan<ObjectBrokerMessage>, output: Port<ObjectBrokerMessage>) {
				// we have to ensure that object 15 is registered. Normally,
				// this is implicitly guaranteed because how would we otherwise
				// know about its id?
				sync_port.recv();

				// want to own object 15
				input.send(OB_RQ_OWN(2,15));

				let response = output.recv();
				match response {
					OB_RQ_DISOWN(1,15,val,2) => {
						assert_eq!(val[0], 0x12 as u8);
						input.send(OB_SHUTDOWN);
					},
					_ => assert!(false),
				}
			}
		);
	}
}

// TODO: tests of more complex scenarios
<|endoftext|>