<commit_before>export t;
export create;
export union;
export intersect;
export copy;
export clone;
export get;
export equal;
export clear;
export set_all;
export invert;
export difference;
export set;
export is_true;
export is_false;
export to_vec;
export to_str;
export eq_vec;

// FIXME: With recursive object types, we could implement binary methods like
//        union, intersection, and difference. At that point, we could write
//        an optimizing version of this module that produces a different obj
//        for the case where nbits <= 32.

// FIXME: Almost all the functions in this module should be state fns, but the
//        effect system isn't currently working correctly.
state type t = rec(vec[mutable uint] storage, uint nbits);

// FIXME: this should be a constant once they work
fn uint_bits() -> uint {
    ret 32u + ((1u << 32u) >> 27u);
}

fn create(uint nbits, bool init) -> t {
    auto elt;
    if (init) {
        elt = ~0u;
    } else {
        elt = 0u;
    }

    auto storage = vec::init_elt_mut[uint](elt, nbits / uint_bits() + 1u);
    ret rec(storage = storage, nbits = nbits);
}

fn process(&fn(uint, uint) -> uint op, &t v0, &t v1) -> bool {
    auto len = vec::len(v1.storage);

    assert (vec::len(v0.storage) == len);
    assert (v0.nbits == v1.nbits);

    auto changed = false;

    for each (uint i in uint::range(0u, len)) {
        auto w0 = v0.storage.(i);
        auto w1 = v1.storage.(i);

        auto w = op(w0, w1);
        if (w0 != w) {
            changed = true;
            v0.storage.(i) = w;
        }
    }

    ret changed;
}

fn lor(uint w0, uint w1) -> uint {
    ret w0 | w1;
}

fn union(&t v0, &t v1) -> bool {
    auto sub = lor;
    ret process(sub, v0, v1);
}

fn land(uint w0, uint w1) -> uint {
    ret w0 & w1;
}

fn intersect(&t v0, &t v1) -> bool {
    auto sub = land;
    ret process(sub, v0, v1);
}

fn right(uint w0, uint w1) -> uint {
    ret w1;
}

fn copy(&t v0, t v1) -> bool {
    auto sub = right;
    ret process(sub, v0, v1);
}

fn clone(t v) -> t {
    auto storage = vec::init_elt_mut[uint](0u, v.nbits / uint_bits() + 1u);
    auto len = vec::len(v.storage);
    for each (uint i in uint::range(0u, len)) {
        storage.(i) = v.storage.(i);
    }
    ret rec(storage = storage, nbits = v.nbits);
}

fn get(&t v, uint i) -> bool {
    assert (i < v.nbits);

    auto bits = uint_bits();

    auto w = i / bits;
    auto b = i % bits;
    auto x = 1u & (v.storage.(w) >> b);
    ret x == 1u;
}

fn equal(&t v0, &t v1) -> bool {
    // FIXME: when we can break or return from inside an iterator loop,
    //        we can eliminate this painful while-loop
    auto len = vec::len(v1.storage);
    auto i = 0u;
    while (i < len) {
        if (v0.storage.(i) != v1.storage.(i)) {
            ret false;
        }
        i = i + 1u;
    }
    ret true;
}

fn clear(&t v) {
    for each (uint i in uint::range(0u, vec::len(v.storage))) {
        v.storage.(i) = 0u;
    }
}

fn set_all(&t v) {
    for each (uint i in uint::range(0u, v.nbits)) {
        set(v, i, true);
    }
}

fn invert(&t v) {
    for each (uint i in uint::range(0u, vec::len(v.storage))) {
        v.storage.(i) = ~v.storage.(i);
    }
}

/* v0 = v0 - v1 */
fn difference(&t v0, &t v1) -> bool {
    invert(v1);
    auto b = intersect(v0, v1);
    invert(v1);
    ret b;
}

fn set(&t v, uint i, bool x) {
    assert (i < v.nbits);

    auto bits = uint_bits();

    auto w = i / bits;
    auto b = i % bits;
    auto w0 = v.storage.(w);
    auto flag = 1u << b;
    if (x) {
        v.storage.(w) = v.storage.(w) | flag;
    } else {
        v.storage.(w) = v.storage.(w) & ~flag;
    }
}

/* true if all bits are 1 */
fn is_true(&t v) -> bool {
    for (uint i in to_vec(v)) {
        if (i != 1u) {
            ret false;
        }
    }

    ret true;
}

/* true if all bits are non-1 */
fn is_false(&t v) -> bool {
    for (uint i in to_vec(v)) {
        if (i == 1u) {
            ret false;
        }
    }

    ret true;
}

fn init_to_vec(t v, uint i) -> uint {
    if (get(v, i)) {
        ret 1u;
    } else {
        ret 0u;
    }
}

fn to_vec(&t v) -> vec[uint] {
    auto sub = bind init_to_vec(v, _);
    ret vec::init_fn[uint](sub, v.nbits);
}

fn to_str(&t v) -> str {
    auto res = "";

    for (uint i in bitv::to_vec(v)) {
        if (i == 1u) {
            res += "1";
        }
        else {
            res += "0";
        }
    }

    ret res;
}

// FIXME: can we just use structural equality on to_vec?
fn eq_vec(&t v0, &vec[uint] v1) -> bool {
    assert (v0.nbits == vec::len[uint](v1));
    auto len = v0.nbits;
    auto i = 0u;
    while (i < len) {
        auto w0 = get(v0, i);
        auto w1 = v1.(i);
        if ((!w0 && w1 != 0u) || (w0 && w1 == 0u)) {
            ret false;
        }
        i = i + 1u;
    }
    ret true;
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<commit_msg>stdlib: Use if/alt expressions in std::bitv<commit_after>export t;
export create;
export union;
export intersect;
export copy;
export clone;
export get;
export equal;
export clear;
export set_all;
export invert;
export difference;
export set;
export is_true;
export is_false;
export to_vec;
export to_str;
export eq_vec;

// FIXME: With recursive object types, we could implement binary methods like
//        union, intersection, and difference. At that point, we could write
//        an optimizing version of this module that produces a different obj
//        for the case where nbits <= 32.

// FIXME: Almost all the functions in this module should be state fns, but the
//        effect system isn't currently working correctly.
state type t = rec(vec[mutable uint] storage, uint nbits);

// FIXME: this should be a constant once they work
fn uint_bits() -> uint {
    ret 32u + ((1u << 32u) >> 27u);
}

fn create(uint nbits, bool init) -> t {
    auto elt = if (init) {
        ~0u
    } else {
        0u
    };

    auto storage = vec::init_elt_mut[uint](elt, nbits / uint_bits() + 1u);
    ret rec(storage = storage, nbits = nbits);
}

fn process(&fn(uint, uint) -> uint op, &t v0, &t v1) -> bool {
    auto len = vec::len(v1.storage);

    assert (vec::len(v0.storage) == len);
    assert (v0.nbits == v1.nbits);

    auto changed = false;

    for each (uint i in uint::range(0u, len)) {
        auto w0 = v0.storage.(i);
        auto w1 = v1.storage.(i);

        auto w = op(w0, w1);
        if (w0 != w) {
            changed = true;
            v0.storage.(i) = w;
        }
    }

    ret changed;
}

fn lor(uint w0, uint w1) -> uint {
    ret w0 | w1;
}

fn union(&t v0, &t v1) -> bool {
    auto sub = lor;
    ret process(sub, v0, v1);
}

fn land(uint w0, uint w1) -> uint {
    ret w0 & w1;
}

fn intersect(&t v0, &t v1) -> bool {
    auto sub = land;
    ret process(sub, v0, v1);
}

fn right(uint w0, uint w1) -> uint {
    ret w1;
}

fn copy(&t v0, t v1) -> bool {
    auto sub = right;
    ret process(sub, v0, v1);
}

fn clone(t v) -> t {
    auto storage = vec::init_elt_mut[uint](0u, v.nbits / uint_bits() + 1u);
    auto len = vec::len(v.storage);
    for each (uint i in uint::range(0u, len)) {
        storage.(i) = v.storage.(i);
    }
    ret rec(storage = storage, nbits = v.nbits);
}

fn get(&t v, uint i) -> bool {
    assert (i < v.nbits);

    auto bits = uint_bits();

    auto w = i / bits;
    auto b = i % bits;
    auto x = 1u & (v.storage.(w) >> b);
    ret x == 1u;
}

fn equal(&t v0, &t v1) -> bool {
    // FIXME: when we can break or return from inside an iterator loop,
    //        we can eliminate this painful while-loop
    auto len = vec::len(v1.storage);
    auto i = 0u;
    while (i < len) {
        if (v0.storage.(i) != v1.storage.(i)) {
            ret false;
        }
        i = i + 1u;
    }
    ret true;
}

fn clear(&t v) {
    for each (uint i in uint::range(0u, vec::len(v.storage))) {
        v.storage.(i) = 0u;
    }
}

fn set_all(&t v) {
    for each (uint i in uint::range(0u, v.nbits)) {
        set(v, i, true);
    }
}

fn invert(&t v) {
    for each (uint i in uint::range(0u, vec::len(v.storage))) {
        v.storage.(i) = ~v.storage.(i);
    }
}

/* v0 = v0 - v1 */
fn difference(&t v0, &t v1) -> bool {
    invert(v1);
    auto b = intersect(v0, v1);
    invert(v1);
    ret b;
}

fn set(&t v, uint i, bool x) {
    assert (i < v.nbits);

    auto bits = uint_bits();

    auto w = i / bits;
    auto b = i % bits;
    auto w0 = v.storage.(w);
    auto flag = 1u << b;
    v.storage.(w) = if (x) {
        v.storage.(w) | flag
    } else {
        v.storage.(w) & ~flag
    };
}

/* true if all bits are 1 */
fn is_true(&t v) -> bool {
    for (uint i in to_vec(v)) {
        if (i != 1u) {
            ret false;
        }
    }

    ret true;
}

/* true if all bits are non-1 */
fn is_false(&t v) -> bool {
    for (uint i in to_vec(v)) {
        if (i == 1u) {
            ret false;
        }
    }

    ret true;
}

fn init_to_vec(t v, uint i) -> uint {
    ret if (get(v, i)) {
        1u
    } else {
        0u
    };
}

fn to_vec(&t v) -> vec[uint] {
    auto sub = bind init_to_vec(v, _);
    ret vec::init_fn[uint](sub, v.nbits);
}

fn to_str(&t v) -> str {
    auto res = "";

    for (uint i in bitv::to_vec(v)) {
        if (i == 1u) {
            res += "1";
        }
        else {
            res += "0";
        }
    }

    ret res;
}

// FIXME: can we just use structural equality on to_vec?
fn eq_vec(&t v0, &vec[uint] v1) -> bool {
    assert (v0.nbits == vec::len[uint](v1));
    auto len = v0.nbits;
    auto i = 0u;
    while (i < len) {
        auto w0 = get(v0, i);
        auto w1 = v1.(i);
        if ((!w0 && w1 != 0u) || (w0 && w1 == 0u)) {
            ret false;
        }
        i = i + 1u;
    }
    ret true;
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<|endoftext|>


<commit_before>// Copyright (C) 2016 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Crowbook is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

//! Misc utility functions used across crowbook

use std;
use std::path::Path;

/// Try to canonicalize a path using std::fs::canonicalize, and returns the
/// unmodified path if it fails (e.g. if the path doesn't exist (yet))
pub fn canonicalize<P: AsRef<Path>>(path: P) -> String {
    if let Ok(path) = std::fs::canonicalize(path.as_ref()) {
        format!("{}", path.display())
    } else {
        format!("{}", path.as_ref().display())
    }
}
<commit_msg>Remove current directory from begginnig of displayed paths<commit_after>// Copyright (C) 2016 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Crowbook is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

//! Misc utility functions used across crowbook

use std;
use std::path::Path;
use std::io::Result;

/// Try to canonicalize a path using std::fs::canonicalize, and returns the
/// unmodified path if it fails (e.g. if the path doesn't exist (yet))
pub fn canonicalize<P: AsRef<Path>>(path: P) -> String {
    try_canonicalize(path.as_ref())
        .unwrap_or(format!("{}", path.as_ref().display()))
}

fn try_canonicalize<P: AsRef<Path>>(path: P) -> Result<String> {
    let path = std::fs::canonicalize(path.as_ref())?;
    let cwd = std::env::current_dir()?;
    Ok(if let Ok(path) = path.strip_prefix(&cwd) {
        format!("{}", path.display())
    } else {
        format!("{}", path.display())
    })
}
<|endoftext|>


<commit_before>import vec::len;
import vec::slice;

type lteq[T] = fn(&T a, &T b) -> bool;

fn merge_sort[T](lteq[T] le, vec[T] v) -> vec[T] {

    fn merge[T](lteq[T] le, vec[T] a, vec[T] b) -> vec[T] {
        let vec[T] res = [];
        let uint a_len = len[T](a);
        let uint a_ix = 0u;
        let uint b_len = len[T](b);
        let uint b_ix = 0u;
        while (a_ix < a_len && b_ix < b_len) {
            if (le(a.(a_ix), b.(b_ix))) {
                res += [a.(a_ix)];
                a_ix += 1u;
            } else {
                res += [b.(b_ix)];
                b_ix += 1u;
            }
        }
        res += slice[T](a, a_ix, a_len);
        res += slice[T](b, b_ix, b_len);
        ret res;
    }

    let uint v_len = len[T](v);

    if (v_len <= 1u) {
        ret v;
    }

    let uint mid = v_len / 2u;
    let vec[T] a = slice[T](v, 0u, mid);
    let vec[T] b = slice[T](v, mid, v_len);
    ret merge[T](le,
                 merge_sort[T](le, a),
                 merge_sort[T](le, b));
}

fn swap[T](vec[mutable T] arr, uint x, uint y) {
    auto a = arr.(x);
    arr.(x) = arr.(y);
    arr.(y) = a;
}

fn part[T](lteq[T] compare_func, vec[mutable T] arr, uint left,
        uint right, uint pivot) -> uint {

    fn compare[T](lteq[T] compare_func, vec[mutable T]arr,
           uint arr_idx, &T arr_value) -> bool {

        ret compare_func(arr.(arr_idx),arr_value);
    }

    auto pivot_value = arr.(pivot);
    swap[T](arr, pivot, right);
    let uint storage_index = left;
    let uint i = left;
    while (i<right) {
        if (compare[T](compare_func, arr, i, pivot_value)) {
           swap[T](arr, i, storage_index);
           storage_index += 1u;
        }
        i += 1u;
    }
    swap[T](arr, storage_index, right);
    ret storage_index;
}

fn qsort[T](lteq[T] compare_func, vec[mutable T] arr, uint left,
        uint right) {

    if (right > left) {
        auto pivot = (left+right)/2u;
        auto new_pivot = part[T](compare_func, arr, left, right, pivot);
        if (new_pivot == 0u) {
             ret;
        }
        qsort[T](compare_func, arr, left, new_pivot - 1u);
        qsort[T](compare_func, arr, new_pivot + 1u, right);
    }
}

fn quick_sort[T](lteq[T] compare_func, vec[mutable T] arr) {

    if (len[T](arr) == 0u) {
        ret;
    }
    qsort[T](compare_func, arr, 0u, (len[T](arr)) - 1u);
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>stdlib: Export only what's needed from std::sort<commit_after>import vec::len;
import vec::slice;

export lteq;
export merge_sort;
export quick_sort;

type lteq[T] = fn(&T a, &T b) -> bool;

fn merge_sort[T](lteq[T] le, vec[T] v) -> vec[T] {

    fn merge[T](lteq[T] le, vec[T] a, vec[T] b) -> vec[T] {
        let vec[T] res = [];
        let uint a_len = len[T](a);
        let uint a_ix = 0u;
        let uint b_len = len[T](b);
        let uint b_ix = 0u;
        while (a_ix < a_len && b_ix < b_len) {
            if (le(a.(a_ix), b.(b_ix))) {
                res += [a.(a_ix)];
                a_ix += 1u;
            } else {
                res += [b.(b_ix)];
                b_ix += 1u;
            }
        }
        res += slice[T](a, a_ix, a_len);
        res += slice[T](b, b_ix, b_len);
        ret res;
    }

    let uint v_len = len[T](v);

    if (v_len <= 1u) {
        ret v;
    }

    let uint mid = v_len / 2u;
    let vec[T] a = slice[T](v, 0u, mid);
    let vec[T] b = slice[T](v, mid, v_len);
    ret merge[T](le,
                 merge_sort[T](le, a),
                 merge_sort[T](le, b));
}

fn swap[T](vec[mutable T] arr, uint x, uint y) {
    auto a = arr.(x);
    arr.(x) = arr.(y);
    arr.(y) = a;
}

fn part[T](lteq[T] compare_func, vec[mutable T] arr, uint left,
        uint right, uint pivot) -> uint {

    fn compare[T](lteq[T] compare_func, vec[mutable T]arr,
           uint arr_idx, &T arr_value) -> bool {

        ret compare_func(arr.(arr_idx),arr_value);
    }

    auto pivot_value = arr.(pivot);
    swap[T](arr, pivot, right);
    let uint storage_index = left;
    let uint i = left;
    while (i<right) {
        if (compare[T](compare_func, arr, i, pivot_value)) {
           swap[T](arr, i, storage_index);
           storage_index += 1u;
        }
        i += 1u;
    }
    swap[T](arr, storage_index, right);
    ret storage_index;
}

fn qsort[T](lteq[T] compare_func, vec[mutable T] arr, uint left,
        uint right) {

    if (right > left) {
        auto pivot = (left+right)/2u;
        auto new_pivot = part[T](compare_func, arr, left, right, pivot);
        if (new_pivot == 0u) {
             ret;
        }
        qsort[T](compare_func, arr, left, new_pivot - 1u);
        qsort[T](compare_func, arr, new_pivot + 1u, right);
    }
}

fn quick_sort[T](lteq[T] compare_func, vec[mutable T] arr) {

    if (len[T](arr) == 0u) {
        ret;
    }
    qsort[T](compare_func, arr, 0u, (len[T](arr)) - 1u);
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>extern crate rand;

use err::size_assert_2d_for_field;

use self::rand::distributions::normal::StandardNormal;

use err::point_assert;

use std::f64::consts::PI;

pub fn torus_distance(field: &Vec<Vec<f64>>, point_1: &[usize; 2], point_2: &[usize; 2]) -> f64 {
    let size = field.len() - 1;

    point_assert(&field, &point_1);
    point_assert(&field, &point_2);

    let i: f64 = if point_1[0] >= point_2[0] {
        point_1[0] as f64 - point_2[0] as f64
    } else {
        point_2[0] as f64 - point_1[0] as f64
    };
    let j: f64 = if point_1[1] >= point_2[1] {
        point_1[1] as f64 - point_2[1] as f64
    } else {
        point_2[1] as f64 - point_1[1] as f64
    };

    let i: f64 = if i > (size as f64) / 2. {
        size as f64 - i
    } else {
        i
    };
    let j: f64 = if j > (size as f64) / 2. {
        size as f64 - j
    } else {
        j
    };

    let arg: f64 = i * i + j * j;

    arg.sqrt()
}

pub fn torus_distance_square(field: &Vec<Vec<f64>>, point_1: &[usize; 2], point_2: &[usize; 2]) -> f64 {
    let size = field.len() - 1;

    point_assert(&field, &point_1);
    point_assert(&field, &point_2);

    let i: f64 = if point_1[0] >= point_2[0] {
        point_1[0] as f64 - point_2[0] as f64
    } else {
        point_2[0] as f64 - point_1[0] as f64
    };
    let j: f64 = if point_1[1] >= point_2[1] {
        point_1[1] as f64 - point_2[1] as f64
    } else {
        point_2[1] as f64 - point_1[1] as f64
    };

    let i: f64 = if i > (size as f64) / 2. {
        size as f64 - i
    } else {
        i
    };
    let j: f64 = if j > (size as f64) / 2. {
        size as f64 - j
    } else {
        j
    };

    let arg: f64 = i * i + j * j;

    arg
}

pub fn angle_for_vector_field(vx: &f64, vy: &f64) -> f64 {
    assert!(*vx != 0. && *vy != 0., "vx and vy equal zero");

    if *vx == 0. {
        if *vy > 0. {
            PI / 2.
        } else {
            -PI / 2.
        }
    } else {
        let tg: f64 = vy / vx;
        let mut phi = tg.atan();

        if *vx < 0. {
            if *vy > 0. {
                phi += PI
            } else {
                phi -= PI
            }
        }
        phi
    }
}

pub fn angle_for_tensor_field(q: &f64, u: &f64) -> f64 {
    assert!(*q != 0. && *u != 0., "q and u equal zero");

    if *q == 0. {
        if *u > 0. {
            PI / 4.
        } else {
            -PI / 4.
        }
    } else {
        let tg: f64 = u / q;
        let mut double_phi = tg.atan();

        if *q < 0. {
            if *u > 0. {
                double_phi += PI
            } else {
                double_phi -= PI
            }
        }
        double_phi / 2.
    }
}

pub fn j_mode_normalized(size: usize, j: usize) -> i32 {
    if j <= size / 2 {
        j as i32
    } else {
        j as i32 - size as i32
    }
}

pub fn fourier_distance(field: &Vec<Vec<f64>>, k1: usize, k2: usize) -> f64 {
    let size = field.len() - 1;

    size_assert_2d_for_field(&field);
    assert!(k1 < (size / 2 + 1));
    assert!(k2 < size);

    let d1 = k1 as f64;
    let d2 = if k2 as f64 <= size as f64 / 2. {
        k2 as f64
    } else {
        k2 as f64 - size as f64
    };

    (d1 * d1 + d2 * d2).sqrt()
}

#[inline]
pub fn normal_generator(mean: f64, std: f64) -> f64 {
    let StandardNormal(x) = rand::random();
    mean + x * std
}

#[inline]
pub fn normal_generator_max(mean: f64, std: f64, arg: f64, max_arg: f64) -> f64 {
    if arg > max_arg {
        mean
    } else {
        normal_generator(mean, std)
    }
}
<commit_msg>fmt fix<commit_after>extern crate rand;

use err::size_assert_2d_for_field;

use self::rand::distributions::normal::StandardNormal;

use err::point_assert;

use std::f64::consts::PI;

pub fn torus_distance(field: &Vec<Vec<f64>>, point_1: &[usize; 2], point_2: &[usize; 2]) -> f64 {
    let size = field.len() - 1;

    point_assert(&field, &point_1);
    point_assert(&field, &point_2);

    let i: f64 = if point_1[0] >= point_2[0] {
        point_1[0] as f64 - point_2[0] as f64
    } else {
        point_2[0] as f64 - point_1[0] as f64
    };
    let j: f64 = if point_1[1] >= point_2[1] {
        point_1[1] as f64 - point_2[1] as f64
    } else {
        point_2[1] as f64 - point_1[1] as f64
    };

    let i: f64 = if i > (size as f64) / 2. {
        size as f64 - i
    } else {
        i
    };
    let j: f64 = if j > (size as f64) / 2. {
        size as f64 - j
    } else {
        j
    };

    let arg: f64 = i * i + j * j;

    arg.sqrt()
}

pub fn torus_distance_square(
    field: &Vec<Vec<f64>>,
    point_1: &[usize; 2],
    point_2: &[usize; 2],
) -> f64 {
    let size = field.len() - 1;

    point_assert(&field, &point_1);
    point_assert(&field, &point_2);

    let i: f64 = if point_1[0] >= point_2[0] {
        point_1[0] as f64 - point_2[0] as f64
    } else {
        point_2[0] as f64 - point_1[0] as f64
    };
    let j: f64 = if point_1[1] >= point_2[1] {
        point_1[1] as f64 - point_2[1] as f64
    } else {
        point_2[1] as f64 - point_1[1] as f64
    };

    let i: f64 = if i > (size as f64) / 2. {
        size as f64 - i
    } else {
        i
    };
    let j: f64 = if j > (size as f64) / 2. {
        size as f64 - j
    } else {
        j
    };

    let arg: f64 = i * i + j * j;

    arg
}

pub fn angle_for_vector_field(vx: &f64, vy: &f64) -> f64 {
    assert!(*vx != 0. && *vy != 0., "vx and vy equal zero");

    if *vx == 0. {
        if *vy > 0. {
            PI / 2.
        } else {
            -PI / 2.
        }
    } else {
        let tg: f64 = vy / vx;
        let mut phi = tg.atan();

        if *vx < 0. {
            if *vy > 0. {
                phi += PI
            } else {
                phi -= PI
            }
        }
        phi
    }
}

pub fn angle_for_tensor_field(q: &f64, u: &f64) -> f64 {
    assert!(*q != 0. && *u != 0., "q and u equal zero");

    if *q == 0. {
        if *u > 0. {
            PI / 4.
        } else {
            -PI / 4.
        }
    } else {
        let tg: f64 = u / q;
        let mut double_phi = tg.atan();

        if *q < 0. {
            if *u > 0. {
                double_phi += PI
            } else {
                double_phi -= PI
            }
        }
        double_phi / 2.
    }
}

pub fn j_mode_normalized(size: usize, j: usize) -> i32 {
    if j <= size / 2 {
        j as i32
    } else {
        j as i32 - size as i32
    }
}

pub fn fourier_distance(field: &Vec<Vec<f64>>, k1: usize, k2: usize) -> f64 {
    let size = field.len() - 1;

    size_assert_2d_for_field(&field);
    assert!(k1 < (size / 2 + 1));
    assert!(k2 < size);

    let d1 = k1 as f64;
    let d2 = if k2 as f64 <= size as f64 / 2. {
        k2 as f64
    } else {
        k2 as f64 - size as f64
    };

    (d1 * d1 + d2 * d2).sqrt()
}

#[inline]
pub fn normal_generator(mean: f64, std: f64) -> f64 {
    let StandardNormal(x) = rand::random();
    mean + x * std
}

#[inline]
pub fn normal_generator_max(mean: f64, std: f64, arg: f64, max_arg: f64) -> f64 {
    if arg > max_arg {
        mean
    } else {
        normal_generator(mean, std)
    }
}
<|endoftext|>


<commit_before>pub use self::os::{datum};
pub use self::os::DBM;
pub use self::os::{DBM_INSERT};
pub use self::os::{DBM_REPLACE};

#[cfg(target_os = "linux")]
#[path = "linux/mod.rs"]
mod os;

pub fn dbm_open<T: ::NTStr>(file: &T, flags: ::int_t, mode: ::int_t) -> *mut DBM {
    extern { fn dbm_open(file: *const ::char_t, flags: ::int_t, mode: ::int_t) -> *mut DBM; }
    unsafe { dbm_open(file.as_ptr(), flags, mode) }
}

pub fn dbm_close(dbf: *mut DBM) {
    extern { fn dbm_close(dbf: *mut DBM); }
    unsafe { dbm_close(dbf) }
}

pub fn dbm_fetch(dbf: *mut DBM, key: datum) -> datum {
    extern { fn dbm_fetch(dbf: *mut DBM, key: datum) -> datum; }
    unsafe { dbm_fetch(dbf, key) }
}

pub fn dbm_store(dbf: *mut DBM, key: datum, content: datum, flags: ::int_t) -> ::int_t {
    extern { fn dbm_store(dbf: *mut DBM, key: datum, content: datum,
                          flags: ::int_t) -> ::int_t; }
    unsafe { dbm_store(dbf, key, content, flags) }
}

pub fn dbm_delete(dbf: *mut DBM, key: datum) -> ::int_t {
    extern { fn dbm_delete(dbf: *mut DBM, key: datum) -> ::int_t; }
    unsafe { dbm_delete(dbf, key) }
}

pub fn dbm_firstkey(dbf: *mut DBM) -> datum {
    extern { fn dbm_firstkey(dbf: *mut DBM) -> datum; }
    unsafe { dbm_firstkey(dbf) }
}

pub fn dbm_nextkey(dbf: *mut DBM) -> datum {
    extern { fn dbm_nextkey(dbf: *mut DBM) -> datum; }
    unsafe { dbm_nextkey(dbf) }
}

pub fn dbm_error(dbf: *mut DBM) -> ::int_t {
    extern { fn dbm_error(dbf: *mut DBM) -> ::int_t; }
    unsafe { dbm_error(dbf) }
}

pub fn dbm_clearerr(dbf: *mut DBM) {
    extern { fn dbm_clearerr(dbf: *mut DBM); }
    unsafe { dbm_clearerr(dbf) }
}
<commit_msg>ndbm.h<commit_after>pub use self::os::{datum};
pub use self::os::DBM;
pub use self::os::{DBM_INSERT};
pub use self::os::{DBM_REPLACE};

use {NTStr, int_t, char_t};

#[cfg(target_os = "linux")]
#[path = "linux/mod.rs"]
mod os;

pub fn dbm_open<T: NTStr>(file: &T, flags: int_t, mode: int_t) -> *mut DBM {
    extern { fn dbm_open(file: *const char_t, flags: int_t, mode: int_t) -> *mut DBM; }
    unsafe { dbm_open(file.as_ptr(), flags, mode) }
}

pub fn dbm_close(dbf: *mut DBM) {
    extern { fn dbm_close(dbf: *mut DBM); }
    unsafe { dbm_close(dbf) }
}

pub fn dbm_fetch(dbf: *mut DBM, key: datum) -> datum {
    extern { fn dbm_fetch(dbf: *mut DBM, key: datum) -> datum; }
    unsafe { dbm_fetch(dbf, key) }
}

pub fn dbm_store(dbf: *mut DBM, key: datum, content: datum, flags: int_t) -> int_t {
    extern { fn dbm_store(dbf: *mut DBM, key: datum, content: datum,
                          flags: int_t) -> int_t; }
    unsafe { dbm_store(dbf, key, content, flags) }
}

pub fn dbm_delete(dbf: *mut DBM, key: datum) -> int_t {
    extern { fn dbm_delete(dbf: *mut DBM, key: datum) -> int_t; }
    unsafe { dbm_delete(dbf, key) }
}

pub fn dbm_firstkey(dbf: *mut DBM) -> datum {
    extern { fn dbm_firstkey(dbf: *mut DBM) -> datum; }
    unsafe { dbm_firstkey(dbf) }
}

pub fn dbm_nextkey(dbf: *mut DBM) -> datum {
    extern { fn dbm_nextkey(dbf: *mut DBM) -> datum; }
    unsafe { dbm_nextkey(dbf) }
}

pub fn dbm_error(dbf: *mut DBM) -> int_t {
    extern { fn dbm_error(dbf: *mut DBM) -> int_t; }
    unsafe { dbm_error(dbf) }
}

pub fn dbm_clearerr(dbf: *mut DBM) {
    extern { fn dbm_clearerr(dbf: *mut DBM); }
    unsafe { dbm_clearerr(dbf) }
}
<|endoftext|>


<commit_before>use std::fmt::Debug;
use std::convert::Into;

/// Encapsulates a floating point number in the range [-1, 1] including both endpoints.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct Closed01Bipolar<F>(F) where F: Copy + Clone + Debug + PartialEq + PartialOrd;

impl Into<f64> for Closed01Bipolar<f64> {
    fn into(self) -> f64 {
        self.get()
    }
}

impl Closed01Bipolar<f64> {
    #[inline(always)]
    pub fn new(f: f64) -> Closed01Bipolar<f64> {
        assert!(f >= -1.0 && f <= 1.0);
        Closed01Bipolar(f)
    }

    #[inline(always)]
    /// Creates a new Closed01Bipolar from `f` clipped to the range [-1, 1].
    pub fn new_clipped(f: f64) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_debug_checked(if f > 1.0 {
            1.0
        } else if f < -1.0 {
            -1.0
        } else {
            f
        })
    }

    #[inline(always)]
    fn new_debug_checked(f: f64) -> Closed01Bipolar<f64> {
        debug_assert!(f >= -1.0 && f <= 1.0);
        Closed01Bipolar(f)
    }

    #[inline(always)]
    pub fn zero() -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_debug_checked(0.0)
    }

    #[inline(always)]
    pub fn negative_one() -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_debug_checked(-1.0)
    }

    #[inline(always)]
    pub fn one() -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_debug_checked(1.0)
    }

    #[inline(always)]
    /// Returns the smaller of the two.
    pub fn min(self, other: Closed01Bipolar<f64>) -> Closed01Bipolar<f64> {
        if self.0 <= other.0 {
            self
        } else {
            other
        }
    }

    #[inline(always)]
    /// Returns the greater of the two.
    pub fn max(self, other: Closed01Bipolar<f64>) -> Closed01Bipolar<f64> {
        if self.0 >= other.0 {
            self
        } else {
            other
        }
    }

    #[inline(always)]
    /// Returns the wrapped value.
    pub fn get(self) -> f64 {
        debug_assert!(self.0 >= -1.0 && self.0 <= 1.0);
        self.0
    }

    #[inline(always)]
    /// Returns the negated value
    pub fn negate(self) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_debug_checked(-self.0)
    }

    #[inline(always)]
    /// Multiplies both numbers
    pub fn mul(self, scalar: Closed01Bipolar<f64>) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_debug_checked(self.get() * scalar.get())
    }
}
<commit_msg>Include the actual value of `f` in the panic message of Closed01Bipolar::new()<commit_after>use std::fmt::Debug;
use std::convert::Into;

/// Encapsulates a floating point number in the range [-1, 1] including both endpoints.
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct Closed01Bipolar<F>(F) where F: Copy + Clone + Debug + PartialEq + PartialOrd;

impl Into<f64> for Closed01Bipolar<f64> {
    fn into(self) -> f64 {
        self.get()
    }
}

impl Closed01Bipolar<f64> {
    #[inline(always)]
    pub fn new(f: f64) -> Closed01Bipolar<f64> {
        if f >= -1.0 && f <= 1.0 {
            Closed01Bipolar(f)
        } else {
            panic!("assertion failed: f >= -1.0 && f <= 1.0; f = {}", f);
        }
    }

    #[inline(always)]
    /// Creates a new Closed01Bipolar from `f` clipped to the range [-1, 1].
    pub fn new_clipped(f: f64) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_debug_checked(if f > 1.0 {
            1.0
        } else if f < -1.0 {
            -1.0
        } else {
            f
        })
    }

    #[inline(always)]
    fn new_debug_checked(f: f64) -> Closed01Bipolar<f64> {
        debug_assert!(f >= -1.0 && f <= 1.0);
        Closed01Bipolar(f)
    }

    #[inline(always)]
    pub fn zero() -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_debug_checked(0.0)
    }

    #[inline(always)]
    pub fn negative_one() -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_debug_checked(-1.0)
    }

    #[inline(always)]
    pub fn one() -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_debug_checked(1.0)
    }

    #[inline(always)]
    /// Returns the smaller of the two.
    pub fn min(self, other: Closed01Bipolar<f64>) -> Closed01Bipolar<f64> {
        if self.0 <= other.0 {
            self
        } else {
            other
        }
    }

    #[inline(always)]
    /// Returns the greater of the two.
    pub fn max(self, other: Closed01Bipolar<f64>) -> Closed01Bipolar<f64> {
        if self.0 >= other.0 {
            self
        } else {
            other
        }
    }

    #[inline(always)]
    /// Returns the wrapped value.
    pub fn get(self) -> f64 {
        debug_assert!(self.0 >= -1.0 && self.0 <= 1.0);
        self.0
    }

    #[inline(always)]
    /// Returns the negated value
    pub fn negate(self) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_debug_checked(-self.0)
    }

    #[inline(always)]
    /// Multiplies both numbers
    pub fn mul(self, scalar: Closed01Bipolar<f64>) -> Closed01Bipolar<f64> {
        Closed01Bipolar::new_debug_checked(self.get() * scalar.get())
    }
}
<|endoftext|>


<commit_before>use std::path::Path;
use std::env;
use std::process::Command;
use super::es::traits::*;
extern crate open;

#[cfg(target_os = "windows")]
pub const EXE: &str = "exe";

#[cfg(not(target_os = "windows"))]
pub const EXE: &str = "";

pub fn open(p: &Path) {
    open::that(p).or_die("cannot open");
}

pub fn edit(p: &Path) {
    let editor = if let Ok(ed) = env::var("VISUAL") {
        ed
    } else
    if let Ok(ed) = env::var("EDITOR") {
        ed
    } else
    if cfg!(target_os = "macos") {
        "emacs".into()
    } else {
        "open".into()
    };
    if editor == "open" {
        open(p);
    } else {
        Command::new(&editor).arg(&p).status().or_die("Cannot find editor");
    }
}

<commit_msg>MacOS: more people know how to get out of vim than emacs<commit_after>use std::path::Path;
use std::env;
use std::process::Command;
use super::es::traits::*;
extern crate open;

#[cfg(target_os = "windows")]
pub const EXE: &str = "exe";

#[cfg(not(target_os = "windows"))]
pub const EXE: &str = "";

pub fn open(p: &Path) {
    open::that(p).or_die("cannot open");
}

pub fn edit(p: &Path) {
    let editor = if let Ok(ed) = env::var("VISUAL") {
        ed
    } else
    if let Ok(ed) = env::var("EDITOR") {
        ed
    } else
    if cfg!(target_os = "macos") {
        "vim".into()
    } else {
        "open".into()
    };
    if editor == "open" {
        open(p);
    } else {
        Command::new(&editor).arg(&p).status().or_die("Cannot find editor");
    }
}

<|endoftext|>


<commit_before>//! Structures and generators for abstract code data.
use std::fmt;
use std::collections::HashMap;
use fmt_code::{FormattedCode, Lang};
use string_gen::keywords::{NAME, TYPE, VALUE};
use error::{CodeSpawnError, Result};

// (element name, attributes (Vec<name, value>), depth in API file structure)
#[doc(hidden)]
pub type CodeData = (String, Vec<(String, String)>, u8);

/// Representation of a single code element.
#[derive(Clone)]
pub struct CodeItem {
    /// Name of the element.
    pub name: String,
    /// List of element's attributes and properties.
    pub attributes: Vec<(String, String)>,
    /// List of child elements.
    pub children: Vec<CodeItem>
}

impl CodeItem {
    #[doc(hidden)]
    pub fn new(item_name: &str, item_attribs: Vec<(String, String)>) -> CodeItem {
        CodeItem {
            name: String::from(item_name),
            attributes: item_attribs,
            children: Vec::<CodeItem>::new()
        }
    }
}

/// Language-specific configuration map.
pub struct CodeConfig {
    /// Name of the configuration (can be `cpp` or `rust`).
    pub name: String,
    /// Maps abstract type to overriden, language-specific type. Can be empty if no overrides are specified in config.
    pub type_dict: HashMap<String, String>,
    /// Maps abstract name to overriden, language-specific name (variables, functions, attributes etc.). Can be empty if no overrides are specified in config.
    pub name_dict: HashMap<String, String>,
    /// List of global configuration data for given language.
    pub global_cfg: HashMap<String, String>
}

impl CodeConfig {
    #[doc(hidden)]
    pub fn new(cfg_name: &str) -> CodeConfig {
        CodeConfig {
            name: String::from(cfg_name),
            type_dict: HashMap::<String, String>::new(),
            name_dict: HashMap::<String, String>::new(),
            global_cfg: HashMap::<String, String>::new()
        }
    }
}

/// Abstract code data representation.
/// Object of this type can be used to generate desired code.
pub struct RawCode {
    /// Map of language-specific configurations.
    pub configs: HashMap<String, CodeConfig>,
    /// A vector of all code elements.
    pub elements: Vec<CodeItem>,
    supported_langs: HashMap<Lang, String>
}

impl RawCode {
    #[doc(hidden)]
    pub fn new() -> RawCode {
        let mut rc = RawCode {
            configs: HashMap::<String, CodeConfig>::new(),
            elements: Vec::<CodeItem>::new(),
            supported_langs: HashMap::<Lang, String>::new()
        };

        rc.supported_langs.insert(Lang::Cpp, String::from("cpp"));
        rc.supported_langs.insert(Lang::Rust, String::from("rust"));

        rc
    }

    /// Converts `RawCode` into C++ `FormattedCode`
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate codespawn;
    ///
    /// let raw_code = codespawn::from_xml("examples/sample.xml").unwrap();
    /// let cpp_code = raw_code.to_cpp();
    /// ```
    pub fn to_cpp(&self) -> Result<FormattedCode> {
        self.to_lang(Lang::Cpp)
    }

    /// Converts `RawCode` into Rust `FormattedCode`
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate codespawn;
    ///
    /// let raw_code = codespawn::from_xml("examples/sample.xml").unwrap();
    /// let cpp_code = raw_code.to_rust();
    /// ```
    pub fn to_rust(&self) -> Result<FormattedCode> {
        self.to_lang(Lang::Rust)
    }

    fn to_lang(&self, lang: Lang) -> Result<FormattedCode> {
        let lang_idx = some_get!(self.supported_langs.get(&lang));
        FormattedCode::new(lang, &self.configs.get(lang_idx), &self.elements)
    }
}

impl fmt::Display for RawCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let _ = write!(f, "<raw data>\n");
        let _ = write!(f, "*\n");
        for e in self.elements.iter() {
            let mut empty_spaces = Vec::<u8>::new();
            print_code_item(e, f, 0, &mut empty_spaces);
        }
        write!(f, "*\n")
    }
}

impl fmt::Display for CodeConfig {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let _ = write!(f, "Config: {}\n", self.name);
        if self.global_cfg.len() > 0 {
            let _ = write!(f, "Settings:\n");
        }
        for (k, v) in &self.global_cfg {
            let _ = write!(f, "  {} = {}\n", k, match v.as_str() {
                "	" => "<tab>", " " => "<space>", _ => v.as_str() });
        }
        if self.name_dict.len() > 0 {
            let _ = write!(f, "Names:\n");
        }
        for (k, v) in &self.name_dict {
            let _ = write!(f, "  {} = {}\n", k, v);
        }
        if self.type_dict.len() > 0 {
            let _ = write!(f, "Types:\n");
        }
        for (k, v) in &self.type_dict {
            let _ = write!(f, "  {} = {}\n", k, v);
        }
        write!(f, "")
    }
}

// used by Display trait to print the tree of elements
#[doc(hidden)]
pub fn print_code_item(e: &CodeItem, f: &mut fmt::Formatter, depth: u8, empty_spaces: &mut Vec<u8>) {
    // indentation
    for i in 0..depth {
        let mut separator = "|";
        for j in empty_spaces.iter() {
            if i == *j {
                separator = " ";
                break;
            }
        }
        let _ = write!(f, "{}  ", separator);
    }

    let _ = write!(f, "|--{}", e.name);
    // print attributes
    if e.attributes.len() > 0 {
        let _ = write!(f, " [");
        for a in 0..e.attributes.len() {
            if a > 0 && a < e.attributes.len() {
                let _ = write!(f, ", ");
            }
            let _ = write!(f, "{}:\"{}\"", e.attributes[a].0, e.attributes[a].1);
        }
        let _ = write!(f, "]");
    }
    let _ = write!(f, "\n");

    // child processing
    if e.children.len() > 0 {
        for c in 0..e.children.len() {
            if (e.children.len() - c) == 1 {
                empty_spaces.push(depth+1);
            }
            else {
                empty_spaces.sort();
                let idx = empty_spaces.binary_search(&(depth+1));
                match idx { Ok(_) => { empty_spaces.remove(idx.unwrap()); }, _ => {} };
            }
            print_code_item(&e.children[c], f, depth+1, empty_spaces);
        }

        // reset space directory when topmost child is reached
        if depth == 1 {
            empty_spaces.clear();
        }
    }
}

// create RawCode element from pre-parsed data
#[doc(hidden)]
pub fn generate_raw(data: &Vec<CodeData>, config_data: &Vec<CodeData>) -> Result<RawCode> {
    let mut raw_code = RawCode::new();

    for i in config_data.iter() {
        if !raw_code.configs.contains_key(&i.0) {
            raw_code.configs.insert(i.0.clone(), CodeConfig::new(&i.0));
        }

        let mut n = String::new();
        let mut t = String::new();
        let mut v = String::new();
        // process all config attributes
        for j in i.1.iter() {
            match j.0.as_str() {
                NAME  => n = j.1.clone(),
                TYPE  => t = j.1.clone(),
                VALUE => v = j.1.clone(),
                _ => { some_get!(raw_code.configs.get_mut(&i.0)).global_cfg.insert(j.0.clone(), j.1.clone()); }
            }
        }

        if n.len() > 0 {
            assert!(some_get!(raw_code.configs.get_mut(&i.0)).name_dict.insert(n.clone(), v.clone()) == None, "Name \"{}\" already defined in config! (duplicate: {}={})", n, n, v);
        }
        if t.len() > 0 {
            assert!(some_get!(raw_code.configs.get_mut(&i.0)).type_dict.insert(t.clone(), v.clone()) == None, "Type \"{}\" already defined in config! (duplicate: {}={}", t, t, v);
        }
    }

    for i in data.iter() {
        // if at depth 0, it's a root element, so add it to the main list
        if i.2 == 0 {
            raw_code.elements.push(CodeItem::new(&i.0, i.1.clone()));
        }
        else {
            // recursively process children of a code element
            fn process_kids(item: &mut CodeItem, depth: u8, name: &str, attribs: &Vec<(String, String)>) -> Result<()> {
                if depth > 1 { try!(process_kids(some_get!(item.children.last_mut()), depth-1, name, attribs)); }
                else         { item.children.push(CodeItem::new(name, attribs.clone())); }

                Ok(())
            }

            let mut parent = some_get!(raw_code.elements.last_mut());
            try!(process_kids(parent, i.2, &i.0, &i.1));
        }
    }

    Ok(raw_code)
}
<commit_msg>remove asserts<commit_after>//! Structures and generators for abstract code data.
use std::fmt;
use std::collections::HashMap;
use fmt_code::{FormattedCode, Lang};
use string_gen::keywords::{NAME, TYPE, VALUE};
use error::{CodeSpawnError, Result};

// (element name, attributes (Vec<name, value>), depth in API file structure)
#[doc(hidden)]
pub type CodeData = (String, Vec<(String, String)>, u8);

/// Representation of a single code element.
#[derive(Clone)]
pub struct CodeItem {
    /// Name of the element.
    pub name: String,
    /// List of element's attributes and properties.
    pub attributes: Vec<(String, String)>,
    /// List of child elements.
    pub children: Vec<CodeItem>
}

impl CodeItem {
    #[doc(hidden)]
    pub fn new(item_name: &str, item_attribs: Vec<(String, String)>) -> CodeItem {
        CodeItem {
            name: String::from(item_name),
            attributes: item_attribs,
            children: Vec::<CodeItem>::new()
        }
    }
}

/// Language-specific configuration map.
pub struct CodeConfig {
    /// Name of the configuration (can be `cpp` or `rust`).
    pub name: String,
    /// Maps abstract type to overriden, language-specific type. Can be empty if no overrides are specified in config.
    pub type_dict: HashMap<String, String>,
    /// Maps abstract name to overriden, language-specific name (variables, functions, attributes etc.). Can be empty if no overrides are specified in config.
    pub name_dict: HashMap<String, String>,
    /// List of global configuration data for given language.
    pub global_cfg: HashMap<String, String>
}

impl CodeConfig {
    #[doc(hidden)]
    pub fn new(cfg_name: &str) -> CodeConfig {
        CodeConfig {
            name: String::from(cfg_name),
            type_dict: HashMap::<String, String>::new(),
            name_dict: HashMap::<String, String>::new(),
            global_cfg: HashMap::<String, String>::new()
        }
    }
}

/// Abstract code data representation.
/// Object of this type can be used to generate desired code.
pub struct RawCode {
    /// Map of language-specific configurations.
    pub configs: HashMap<String, CodeConfig>,
    /// A vector of all code elements.
    pub elements: Vec<CodeItem>,
    supported_langs: HashMap<Lang, String>
}

impl RawCode {
    #[doc(hidden)]
    pub fn new() -> RawCode {
        let mut rc = RawCode {
            configs: HashMap::<String, CodeConfig>::new(),
            elements: Vec::<CodeItem>::new(),
            supported_langs: HashMap::<Lang, String>::new()
        };

        rc.supported_langs.insert(Lang::Cpp, String::from("cpp"));
        rc.supported_langs.insert(Lang::Rust, String::from("rust"));

        rc
    }

    /// Converts `RawCode` into C++ `FormattedCode`
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate codespawn;
    ///
    /// let raw_code = codespawn::from_xml("examples/sample.xml").unwrap();
    /// let cpp_code = raw_code.to_cpp();
    /// ```
    pub fn to_cpp(&self) -> Result<FormattedCode> {
        self.to_lang(Lang::Cpp)
    }

    /// Converts `RawCode` into Rust `FormattedCode`
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate codespawn;
    ///
    /// let raw_code = codespawn::from_xml("examples/sample.xml").unwrap();
    /// let cpp_code = raw_code.to_rust();
    /// ```
    pub fn to_rust(&self) -> Result<FormattedCode> {
        self.to_lang(Lang::Rust)
    }

    fn to_lang(&self, lang: Lang) -> Result<FormattedCode> {
        let lang_idx = some_get!(self.supported_langs.get(&lang));
        FormattedCode::new(lang, &self.configs.get(lang_idx), &self.elements)
    }
}

impl fmt::Display for RawCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let _ = write!(f, "<raw data>\n");
        let _ = write!(f, "*\n");
        for e in self.elements.iter() {
            let mut empty_spaces = Vec::<u8>::new();
            print_code_item(e, f, 0, &mut empty_spaces);
        }
        write!(f, "*\n")
    }
}

impl fmt::Display for CodeConfig {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let _ = write!(f, "Config: {}\n", self.name);
        if self.global_cfg.len() > 0 {
            let _ = write!(f, "Settings:\n");
        }
        for (k, v) in &self.global_cfg {
            let _ = write!(f, "  {} = {}\n", k, match v.as_str() {
                "	" => "<tab>", " " => "<space>", _ => v.as_str() });
        }
        if self.name_dict.len() > 0 {
            let _ = write!(f, "Names:\n");
        }
        for (k, v) in &self.name_dict {
            let _ = write!(f, "  {} = {}\n", k, v);
        }
        if self.type_dict.len() > 0 {
            let _ = write!(f, "Types:\n");
        }
        for (k, v) in &self.type_dict {
            let _ = write!(f, "  {} = {}\n", k, v);
        }
        write!(f, "")
    }
}

// used by Display trait to print the tree of elements
#[doc(hidden)]
pub fn print_code_item(e: &CodeItem, f: &mut fmt::Formatter, depth: u8, empty_spaces: &mut Vec<u8>) {
    // indentation
    for i in 0..depth {
        let mut separator = "|";
        for j in empty_spaces.iter() {
            if i == *j {
                separator = " ";
                break;
            }
        }
        let _ = write!(f, "{}  ", separator);
    }

    let _ = write!(f, "|--{}", e.name);
    // print attributes
    if e.attributes.len() > 0 {
        let _ = write!(f, " [");
        for a in 0..e.attributes.len() {
            if a > 0 && a < e.attributes.len() {
                let _ = write!(f, ", ");
            }
            let _ = write!(f, "{}:\"{}\"", e.attributes[a].0, e.attributes[a].1);
        }
        let _ = write!(f, "]");
    }
    let _ = write!(f, "\n");

    // child processing
    if e.children.len() > 0 {
        for c in 0..e.children.len() {
            if (e.children.len() - c) == 1 {
                empty_spaces.push(depth+1);
            }
            else {
                empty_spaces.sort();
                let idx = empty_spaces.binary_search(&(depth+1));
                match idx { Ok(_) => { empty_spaces.remove(idx.unwrap()); }, _ => {} };
            }
            print_code_item(&e.children[c], f, depth+1, empty_spaces);
        }

        // reset space directory when topmost child is reached
        if depth == 1 {
            empty_spaces.clear();
        }
    }
}

// create RawCode element from pre-parsed data
#[doc(hidden)]
pub fn generate_raw(data: &Vec<CodeData>, config_data: &Vec<CodeData>) -> Result<RawCode> {
    let mut raw_code = RawCode::new();

    for i in config_data.iter() {
        if !raw_code.configs.contains_key(&i.0) {
            raw_code.configs.insert(i.0.clone(), CodeConfig::new(&i.0));
        }

        let mut n = String::new();
        let mut t = String::new();
        let mut v = String::new();
        // process all config attributes
        for j in i.1.iter() {
            match j.0.as_str() {
                NAME  => n = j.1.clone(),
                TYPE  => t = j.1.clone(),
                VALUE => v = j.1.clone(),
                _ => { some_get!(raw_code.configs.get_mut(&i.0)).global_cfg.insert(j.0.clone(), j.1.clone()); }
            }
        }

        if n.len() > 0 {
            some_get!(raw_code.configs.get_mut(&i.0)).name_dict.insert(n.clone(), v.clone());
        }
        if t.len() > 0 {
            some_get!(raw_code.configs.get_mut(&i.0)).type_dict.insert(t.clone(), v.clone());
        }
    }

    for i in data.iter() {
        // if at depth 0, it's a root element, so add it to the main list
        if i.2 == 0 {
            raw_code.elements.push(CodeItem::new(&i.0, i.1.clone()));
        }
        else {
            // recursively process children of a code element
            fn process_kids(item: &mut CodeItem, depth: u8, name: &str, attribs: &Vec<(String, String)>) -> Result<()> {
                if depth > 1 { try!(process_kids(some_get!(item.children.last_mut()), depth-1, name, attribs)); }
                else         { item.children.push(CodeItem::new(name, attribs.clone())); }

                Ok(())
            }

            let mut parent = some_get!(raw_code.elements.last_mut());
            try!(process_kids(parent, i.2, &i.0, &i.1));
        }
    }

    Ok(raw_code)
}
<|endoftext|>


<commit_before>// Register allocator.
//
// Before this pass, it is assumed that we have infinite number of
// registers. This pass maps them to a finite number of registers.
// We actually have only 7 registers.
//
// We allocate registers only within a single expression. In other
// words, there are no registers that live beyond semicolons.
// This design choice simplifies the implementation a lot, since
// practically we don't have to think about the case in which
// registers are exhausted and need to be spilled to memory.

#![allow(non_upper_case_globals)]

use crate::gen_ir::*;
use crate::irdump::*;
use crate::*;

lazy_static! {
    static ref USED: Mutex<Vec<bool>> = Mutex::new(Vec::new());
    static ref REG_MAP: Mutex<Vec<i32>> = Mutex::new(Vec::new());
}

const reg_map_size: usize = 8192;

pub const regs: [&'static str; 7] = ["r10", "r11", "rbx", "r12", "r13", "r14", "r15"];
pub const regs8: [&'static str; 7] = ["r10b", "r11b", "bl", "r12b", "r13b", "r14b", "r15b"];
pub const regs32: [&'static str; 7] = ["r10d", "r11d", "ebx", "r12d", "r13d", "r14d", "r15d"];

fn init_used() {
    match USED.lock() {
        Ok(mut used) => {
            *used = Vec::new();
            for _i in 0..regs.len() {
                used.push(false);
            }
        }
        _ => {
            panic!();
        }
    }
}

fn init_reg_map() {
    match REG_MAP.lock() {
        Ok(mut reg_map) => {
            *reg_map = Vec::new();
            for _i in 0..reg_map_size {
                reg_map.push(-1);
            }
        }
        _ => {
            panic!();
        }
    }
}

fn alloc(ir_reg: i32) -> i32 {
    let mut reg_map = REG_MAP.lock().unwrap();
    if reg_map[ir_reg as usize] != -1 {
        let r = reg_map[ir_reg as usize];
        assert!(USED.lock().unwrap()[r as usize]);
        return r;
    }

    let mut used = USED.lock().unwrap();
    for i in 0..regs.len() {
        if used[i] {
            continue;
        }
        reg_map[ir_reg as usize] = i as i32;
        used[i] = true;
        return i as i32;
    }
    panic!("register exhausted");
}

fn visit(irv: &mut Vec<IR>) {
    for i in 0..irv.len() {
        let mut ir = &mut irv[i];

        match irinfo_get(&ir.op).unwrap().ty {
            IRInfoType::REG |
                IRInfoType::REG_IMM |
                IRInfoType::REG_LABEL |
                IRInfoType::LABEL_ADDR => {
                ir.lhs = alloc(ir.lhs);
            }
            IRInfoType::REG_REG => {
                ir.lhs = alloc(ir.lhs);
                ir.rhs = alloc(ir.rhs);
            }
            IRInfoType::CALL => {
                ir.lhs = alloc(ir.lhs);
                for i in 0..ir.nargs {
                    ir.args[i] = alloc(ir.args[i]);
                }
            }
            _ => {}
        }

        if ir.op == IRType::KILL {
            let mut used = USED.lock().unwrap();
            assert!(used[ir.lhs as usize]);
            used[ir.lhs as usize] = false;
            ir.op = IRType::NOP;
        }
    }
}

pub fn alloc_regs(fns: &mut Vec<IR>) {
    init_reg_map();
    init_used();
    for i in 0..fns.len() {
        let fun = &mut fns[i];
        visit(&mut fun.ir);
    }
}
<commit_msg>Add a safety guard.<commit_after>// Register allocator.
//
// Before this pass, it is assumed that we have infinite number of
// registers. This pass maps them to a finite number of registers.
// We actually have only 7 registers.
//
// We allocate registers only within a single expression. In other
// words, there are no registers that live beyond semicolons.
// This design choice simplifies the implementation a lot, since
// practically we don't have to think about the case in which
// registers are exhausted and need to be spilled to memory.

#![allow(non_upper_case_globals)]

use crate::gen_ir::*;
use crate::irdump::*;
use crate::*;

lazy_static! {
    static ref USED: Mutex<Vec<bool>> = Mutex::new(Vec::new());
    static ref REG_MAP: Mutex<Vec<i32>> = Mutex::new(Vec::new());
}

const reg_map_size: usize = 8192;

pub const regs: [&'static str; 7] = ["r10", "r11", "rbx", "r12", "r13", "r14", "r15"];
pub const regs8: [&'static str; 7] = ["r10b", "r11b", "bl", "r12b", "r13b", "r14b", "r15b"];
pub const regs32: [&'static str; 7] = ["r10d", "r11d", "ebx", "r12d", "r13d", "r14d", "r15d"];

fn init_used() {
    match USED.lock() {
        Ok(mut used) => {
            *used = Vec::new();
            for _i in 0..regs.len() {
                used.push(false);
            }
        }
        _ => {
            panic!();
        }
    }
}

fn init_reg_map() {
    match REG_MAP.lock() {
        Ok(mut reg_map) => {
            *reg_map = Vec::new();
            for _i in 0..reg_map_size {
                reg_map.push(-1);
            }
        }
        _ => {
            panic!();
        }
    }
}

fn alloc(ir_reg: i32) -> i32 {
    if reg_map_size <= ir_reg as usize {
        panic!("program too big");
    }

    let mut reg_map = REG_MAP.lock().unwrap();
    if reg_map[ir_reg as usize] != -1 {
        let r = reg_map[ir_reg as usize];
        assert!(USED.lock().unwrap()[r as usize]);
        return r;
    }

    let mut used = USED.lock().unwrap();
    for i in 0..reg_map_size {
        if used[i] {
            continue;
        }
        reg_map[ir_reg as usize] = i as i32;
        used[i] = true;
        return i as i32;
    }
    panic!("register exhausted");
}

fn visit(irv: &mut Vec<IR>) {
    for i in 0..irv.len() {
        let mut ir = &mut irv[i];

        match irinfo_get(&ir.op).unwrap().ty {
            IRInfoType::REG |
                IRInfoType::REG_IMM |
                IRInfoType::REG_LABEL |
                IRInfoType::LABEL_ADDR => {
                ir.lhs = alloc(ir.lhs);
            }
            IRInfoType::REG_REG => {
                ir.lhs = alloc(ir.lhs);
                ir.rhs = alloc(ir.rhs);
            }
            IRInfoType::CALL => {
                ir.lhs = alloc(ir.lhs);
                for i in 0..ir.nargs {
                    ir.args[i] = alloc(ir.args[i]);
                }
            }
            _ => {}
        }

        if ir.op == IRType::KILL {
            let mut used = USED.lock().unwrap();
            assert!(used[ir.lhs as usize]);
            used[ir.lhs as usize] = false;
            ir.op = IRType::NOP;
        }
    }
}

pub fn alloc_regs(fns: &mut Vec<IR>) {
    init_reg_map();
    init_used();
    for i in 0..fns.len() {
        let fun = &mut fns[i];
        visit(&mut fun.ir);
    }
}
<|endoftext|>


<commit_before>// Copyright(C) 2016 Chris Liebert
extern crate glium;
extern crate image;
extern crate nalgebra;

use std::collections::HashMap;

use common;
use glium::backend::glutin_backend::GlutinFacade;
use glium::Program;
use glium::Surface;
use self::nalgebra::{Matrix4, PerspectiveMatrix3};

use common::{Scene, Vertex8f32};
implement_vertex!(Vertex8f32, position, normal, texcoord);

pub struct Renderer {
	pub index_buffer: glium::index::NoIndices,
	pub modelview_matrix_array: [[f32; 4]; 4],
	pub program: Program,
	pub projection_matrix: Matrix4<f32>,
	pub scene: Scene,
	pub textures: HashMap<String, glium::texture::CompressedSrgbTexture2d>,
	pub vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>>,
}

impl Renderer {
	pub fn new(display: &GlutinFacade, scene: Scene) -> Renderer {

		let mut vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>> =
			Vec::with_capacity(scene.meshes.len());

		for i in 0..scene.meshes.len() {
			vertex_buffers.push(glium::vertex::VertexBuffer::new(display, &scene.meshes[i].vertices).unwrap());
		}

		let index_buffer: glium::index::NoIndices =
			glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

		if scene.shaders.len() == 0 {
			panic!("No shaders loaded");
		}

		let mut textures: HashMap<String, glium::texture::CompressedSrgbTexture2d> = HashMap::new();

		for i in 0..scene.images.len() {
			//TODO: determine image format by name extension if nessisary
			//let image = image::load_from_memory_with_format(&scene.images[i].image, image::PNG).unwrap().to_rgba();
			let image = image::load_from_memory(&scene.images[i].image).unwrap().to_rgba();

			let image_dimensions = image.dimensions();
			let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(),
			                                                               image_dimensions);
			let opengl_texture: glium::texture::CompressedSrgbTexture2d =
				glium::texture::CompressedSrgbTexture2d::new(display, image).unwrap();
			textures.insert(scene.images[i].name.clone(), opengl_texture);
		}

		// Load the first shader in the database by default
		// TODO: load from config settings table?
		let shader_index = 0;

		// println!("Using glsl version {}", glsl_version);

		let program: Program = program!(display,
			/*
				110 => {
					vertex: &scene.shaders[shader_index].vertex_source_110,
					fragment: &scene.shaders[shader_index].fragment_source_110,
				},
				120 => {
					vertex: &scene.shaders[shader_index].vertex_source_120,
					fragment: &scene.shaders[shader_index].fragment_source_120,
				},
				130 => {
					vertex: &scene.shaders[shader_index].vertex_source_130,
					fragment: &scene.shaders[shader_index].fragment_source_130,
				},
				*/
				140 => {
					vertex: &scene.shaders[shader_index].vertex_source_140,
					fragment: &scene.shaders[shader_index].fragment_source_140,
				},
				/*
				150 => {
					vertex: &scene.shaders[shader_index].vertex_source_150,
					fragment: &scene.shaders[shader_index].fragment_source_150,
				},
				300 => {
					vertex: &scene.shaders[shader_index].vertex_source_300,
					fragment: &scene.shaders[shader_index].fragment_source_300,
				},
				330 => {
					vertex: &scene.shaders[shader_index].vertex_source_330,
					fragment: &scene.shaders[shader_index].fragment_source_330,
				},
				400 => {
					vertex: &scene.shaders[shader_index].vertex_source_400,
					fragment: &scene.shaders[shader_index].fragment_source_400,
				},
				410 => {
					vertex: &scene.shaders[shader_index].vertex_source_410,
					fragment: &scene.shaders[shader_index].fragment_source_410,
				},
				420 => {
					vertex: &scene.shaders[shader_index].vertex_source_420,
					fragment: &scene.shaders[shader_index].fragment_source_420,
				},
				430 => {
					vertex: &scene.shaders[shader_index].vertex_source_430,
					fragment: &scene.shaders[shader_index].fragment_source_430,
				},
				100 es => {
					vertex: &scene.shaders[shader_index].vertex_source_100es,
					fragment: &scene.shaders[shader_index].fragment_source_100es,
				},
				300 es => {
					vertex: &scene.shaders[shader_index].vertex_source_300es,
					fragment: &scene.shaders[shader_index].fragment_source_300es,
				}, */
			)
			.unwrap();

		// Shader compilation no longer required
		display.release_shader_compiler();

		// Get the screen width and height in pixels
		let screen_width: u32;
		let screen_height: u32;
		match display.get_window() {
			Some(window) =>  {
				let pixel_dimensions: (u32,u32) = window.get_inner_size_pixels().unwrap();
				screen_width = pixel_dimensions.0;
				screen_height = pixel_dimensions.1;
			},
			None => {
				panic!("Error retrieving window when querying display size.");
			}
		}

		// Set up camera
		let projection_matrix = PerspectiveMatrix3::new(screen_width as f32 / screen_height as f32,
		                                          45.0,
		                                          0.1,
		                                          1000.0);
		let projection_matrix_array: Matrix4<f32> = projection_matrix.to_matrix();

		let modelview_matrix_array = [[1.0f32, -0.0f32, -0.0f32, 0.0f32],
		                          [0.0f32, 1.0f32, -0.0f32, 0.0f32],
		                          [0.0f32, 0.0f32, 1.0f32, 0.0f32],
		                          [-5.0f32, -3.0f32, -12.0f32, 1.0f32]];
		Renderer {
			index_buffer: index_buffer,
			modelview_matrix_array: modelview_matrix_array,
			program: program,
			projection_matrix: projection_matrix_array,
			scene: scene,
			textures: textures,
			vertex_buffers: vertex_buffers,
		}
	}

	pub fn render(&self, display: &GlutinFacade) {
		let mut target = display.draw();
		// TODO: generate this texture instead of loading from sqlite
		let default_blank_texture = &self.textures["DEFAULT_BLANK_TEXTURE.png"];
		target.clear_color(0.0, 0.0, 0.0, 1.0);
		for i in 0..self.vertex_buffers.len() as usize {
			let material_index: usize = self.scene.meshes[i].material_index.clone();
			let diffuse = self.scene.materials[material_index].diffuse.clone();
			let diffuse_texname: String =
				self.scene.materials[material_index].diffuse_texname.clone();
			let opengl_texture: &glium::texture::CompressedSrgbTexture2d;
			if diffuse_texname.len() == 0 {
				opengl_texture = &default_blank_texture;
			} else {
				match self.textures.get(&diffuse_texname) {
					Some(t) => {
						opengl_texture = &t;
					},
					None => {
						println!("Unable to load {}, using blank texture instead.", diffuse_texname);
						opengl_texture = &default_blank_texture;
					},
				}
			}
			let uniforms: glium::uniforms::UniformsStorage<_, _> = uniform! {
				projection: *self.projection_matrix.as_ref(),
				modelview: self.modelview_matrix_array,
				light_position_worldspace: [2.0, 10.0, 1.0f32],
				diffuse: diffuse,
				diffuse_texture: opengl_texture,
			};

			target.draw(&self.vertex_buffers[i],
				&self.index_buffer,
				&self.program,
				&uniforms,
				&Default::default())
				.unwrap();
		}
		target.finish().unwrap();
	}
}
<commit_msg>changed render interface to pass the shader to the render method.<commit_after>// Copyright(C) 2016 Chris Liebert
extern crate glium;
extern crate image;
extern crate nalgebra;

use std::collections::HashMap;

use common;
use common::{Material, Scene, Shader, Vertex8f32};
use loader::DBLoader;

use glium::backend::glutin_backend::GlutinFacade;
use glium::Program;
use glium::Surface;
use self::nalgebra::{Matrix4, PerspectiveMatrix3};

implement_vertex!(Vertex8f32, position, normal, texcoord);

pub struct Renderer {
	pub index_buffer: glium::index::NoIndices,
	pub modelview_matrix_array: [[f32; 4]; 4],
	pub projection_matrix: Matrix4<f32>,
	pub scene: Scene,
	pub textures: HashMap<String, glium::texture::CompressedSrgbTexture2d>,
	pub vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>>,
}

impl Renderer {
	pub fn new(display: &GlutinFacade, scene: Scene) -> Renderer {

		let mut vertex_buffers: Vec<glium::vertex::VertexBuffer<common::Vertex8f32>> =
			Vec::with_capacity(scene.meshes.len());

		for i in 0..scene.meshes.len() {
			vertex_buffers.push(glium::vertex::VertexBuffer::new(display, &scene.meshes[i].vertices).unwrap());
		}

		let index_buffer: glium::index::NoIndices =
			glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

	/*
		if scene.shaders.len() == 0 {
			panic!("No shaders loaded");
		}
	*/

		let mut textures: HashMap<String, glium::texture::CompressedSrgbTexture2d> = HashMap::new();

		for i in 0..scene.images.len() {
			//TODO: determine image format by name extension if nessisary
			//let image = image::load_from_memory_with_format(&scene.images[i].image, image::PNG).unwrap().to_rgba();
			let image = image::load_from_memory(&scene.images[i].image).unwrap().to_rgba();

			let image_dimensions = image.dimensions();
			let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(),
			                                                               image_dimensions);
			let opengl_texture: glium::texture::CompressedSrgbTexture2d =
				glium::texture::CompressedSrgbTexture2d::new(display, image).unwrap();
			textures.insert(scene.images[i].name.clone(), opengl_texture);
		}

		// Get the screen width and height in pixels
		let screen_width: u32;
		let screen_height: u32;
		match display.get_window() {
			Some(window) =>  {
				let pixel_dimensions: (u32,u32) = window.get_inner_size_pixels().unwrap();
				screen_width = pixel_dimensions.0;
				screen_height = pixel_dimensions.1;
			},
			None => {
				panic!("Error retrieving window when querying display size.");
			}
		}

		// Set up camera
		let projection_matrix = PerspectiveMatrix3::new(screen_width as f32 / screen_height as f32,
		                                          45.0,
		                                          0.1,
		                                          1000.0);
		let projection_matrix_array: Matrix4<f32> = projection_matrix.to_matrix();

		let modelview_matrix_array = [[1.0f32, -0.0f32, -0.0f32, 0.0f32],
		                          [0.0f32, 1.0f32, -0.0f32, 0.0f32],
		                          [0.0f32, 0.0f32, 1.0f32, 0.0f32],
		                          [-5.0f32, -3.0f32, -12.0f32, 1.0f32]];
		Renderer {
			index_buffer: index_buffer,
			modelview_matrix_array: modelview_matrix_array,
			projection_matrix: projection_matrix_array,
			scene: scene,
			textures: textures,
			vertex_buffers: vertex_buffers,
		}
	}

	pub fn create_shader_program(&self, shader_name: &str, dbloader: &DBLoader, display: &GlutinFacade) -> glium::program::Program {

		//todo: determine with glium
		let use_gles = false; // Use OpenGLES instead of OpenGL (for mobile devices)
		let glsl_version = 110;
		let glsl_version_string = "110";//for GLES, use 300 es

		// Load the first shader in the database by default
		// TODO: load from config settings table?
		let shader_index = 0;

		// println!("Using glsl version {}", glsl_version);

		let shader: Shader = dbloader.load_shader(shader_name, glsl_version_string);

		//todo add support for Es after glsl_version in macro for GLES
		let program: Program = program!(display,
				glsl_version => {
					vertex: &shader.vertex_source,
					fragment: &shader.fragment_source,
				},
			)
			.unwrap();

		// Shader compilation no longer required
		display.release_shader_compiler();
		return program;
	}

	pub fn render(&self, display: &GlutinFacade, program: &glium::program::Program) {
		let mut target = display.draw();
		// TODO: generate this texture instead of loading from sqlite
		let default_blank_texture = &self.textures["DEFAULT_BLANK_TEXTURE.png"];
		target.clear_color(0.0, 0.0, 0.0, 1.0);
		for i in 0..self.vertex_buffers.len() as usize {
			let material_index: usize = self.scene.meshes[i].material_index.clone();
			let diffuse = self.scene.materials[material_index].diffuse.clone();
			let diffuse_texname: String =
				self.scene.materials[material_index].diffuse_texname.clone();
			let opengl_texture: &glium::texture::CompressedSrgbTexture2d;
			if diffuse_texname.len() == 0 {
				opengl_texture = &default_blank_texture;
			} else {
				match self.textures.get(&diffuse_texname) {
					Some(t) => {
						opengl_texture = &t;
					},
					None => {
						println!("Unable to load {}, using blank texture instead.", diffuse_texname);
						opengl_texture = &default_blank_texture;
					},
				}
			}
			let uniforms: glium::uniforms::UniformsStorage<_, _> = uniform! {
				projection: *self.projection_matrix.as_ref(),
				modelview: self.modelview_matrix_array,
				light_position_worldspace: [2.0, 10.0, 1.0f32],
				diffuse: diffuse,
				diffuse_texture: opengl_texture,
			};

			target.draw(&self.vertex_buffers[i],
				&self.index_buffer,
				program,
				&uniforms,
				&Default::default())
				.unwrap();
		}
		target.finish().unwrap();
	}
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fs::{ File, OpenOptions };
use std::io::{ Read, Write };

use rustc::ty::layout::Size;

use crate::stacked_borrows::Tag;
use crate::*;

pub struct FileHandle {
    file: File,
    flag: i32,
}

pub struct FileHandler {
    handles: HashMap<i32, FileHandle>,
    low: i32,
}

impl Default for FileHandler {
    fn default() -> Self {
        FileHandler {
            handles: Default::default(),
            // 0, 1 and 2 are reserved for stdin, stdout and stderr
            low: 3,
        }
    }
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn open(
        &mut self,
        path_op: OpTy<'tcx, Tag>,
        flag_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`open` not available when isolation is enabled")
        }

        let flag = this.read_scalar(flag_op)?.to_i32()?;

        let mut options = OpenOptions::new();

        // The first two bits of the flag correspond to the access mode of the file in linux.
        let access_mode = flag & 0b11;

        if access_mode == this.eval_libc_i32("O_RDONLY")? {
            options.read(true);
        } else if access_mode == this.eval_libc_i32("O_WRONLY")? {
            options.write(true);
        } else if access_mode == this.eval_libc_i32("O_RDWR")? {
            options.read(true).write(true);
        } else {
            throw_unsup_format!("Unsupported access mode {:#x}", access_mode);
        }

        if flag & this.eval_libc_i32("O_APPEND")? != 0 {
            options.append(true);
        }
        if flag & this.eval_libc_i32("O_TRUNC")? != 0 {
            options.truncate(true);
        }
        if flag & this.eval_libc_i32("O_CREAT")? != 0 {
            options.create(true);
        }

        let path_bytes = this
            .memory()
            .read_c_str(this.read_scalar(path_op)?.not_undef()?)?;
        let path = std::str::from_utf8(path_bytes)
            .map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", path_bytes))?;

        let fd = options.open(path).map(|file| {
            let mut fh = &mut this.machine.file_handler;
            fh.low += 1;
            fh.handles.insert(fh.low, FileHandle { file, flag });
            fh.low
        });

        this.consume_result(fd)
    }

    fn fcntl(
        &mut self,
        fd_op: OpTy<'tcx, Tag>,
        cmd_op: OpTy<'tcx, Tag>,
        arg_op: Option<OpTy<'tcx, Tag>>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`fcntl` not available when isolation is enabled")
        }

        let fd = this.read_scalar(fd_op)?.to_i32()?;
        let cmd = this.read_scalar(cmd_op)?.to_i32()?;

        if cmd == this.eval_libc_i32("F_SETFD")? {
            // This does not affect the file itself. Certain flags might require changing the file
            // or the way it is accessed somehow.
            let flag = this.read_scalar(arg_op.unwrap())?.to_i32()?;
            // The only usage of this in stdlib at the moment is to enable the `FD_CLOEXEC` flag.
            let fd_cloexec = this.eval_libc_i32("FD_CLOEXEC")?;
            if let Some(FileHandle { flag: old_flag, .. }) =
                this.machine.file_handler.handles.get_mut(&fd)
            {
                if flag ^ *old_flag == fd_cloexec {
                    *old_flag = flag;
                } else {
                    throw_unsup_format!("Unsupported arg {:#x} for `F_SETFD`", flag);
                }
            }
            Ok(0)
        } else if cmd == this.eval_libc_i32("F_GETFD")? {
            this.get_handle_and(fd, |handle| Ok(handle.flag))
        } else {
            throw_unsup_format!("Unsupported command {:#x}", cmd);
        }
    }

    fn close(&mut self, fd_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`close` not available when isolation is enabled")
        }

        let fd = this.read_scalar(fd_op)?.to_i32()?;

        this.remove_handle_and(
            fd,
            |handle, this| this.consume_result(handle.file.sync_all().map(|_| 0i32)),
        )
    }

    fn read(
        &mut self,
        fd_op: OpTy<'tcx, Tag>,
        buf_op: OpTy<'tcx, Tag>,
        count_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i64> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`read` not available when isolation is enabled")
        }

        let tcx = &{ this.tcx.tcx };

        let fd = this.read_scalar(fd_op)?.to_i32()?;
        let buf = this.force_ptr(this.read_scalar(buf_op)?.not_undef()?)?;
        let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;

        // Remove the file handle to avoid borrowing issues
        this.remove_handle_and(
            fd,
            |mut handle, this| {
                let bytes = handle
                    .file
                    .read(this.memory_mut().get_mut(buf.alloc_id)?.get_bytes_mut(
                        tcx,
                        buf,
                        Size::from_bytes(count),
                    )?)
                    .map(|bytes| bytes as i64);
                // Reinsert the file handle
                this.machine.file_handler.handles.insert(fd, handle);
                this.consume_result(bytes)
            },
        )
    }

    fn write(
        &mut self,
        fd_op: OpTy<'tcx, Tag>,
        buf_op: OpTy<'tcx, Tag>,
        count_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i64> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`write` not available when isolation is enabled")
        }

        let tcx = &{ this.tcx.tcx };

        let fd = this.read_scalar(fd_op)?.to_i32()?;
        let buf = this.force_ptr(this.read_scalar(buf_op)?.not_undef()?)?;
        let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;

        // `to_vec` is needed to avoid borrowing issues when writing to the file.
        let bytes = this.memory().get(buf.alloc_id)?.get_bytes(tcx, buf, Size::from_bytes(count))?.to_vec();

        this.remove_handle_and(fd, |mut handle, this| {
            let bytes = handle.file.write(&bytes).map(|bytes| bytes as i64);
            this.machine.file_handler.handles.insert(fd, handle);
            this.consume_result(bytes)
        })
    }

    /// Helper function that gets a `FileHandle` immutable reference and allows to manipulate it
    /// using the `f` closure.
    ///
    /// If the `fd` file descriptor does not correspond to a file, this functions returns `Ok(-1)`
    /// and sets `Evaluator::last_error` to `libc::EBADF` (invalid file descriptor).
    ///
    /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
    /// functions return different integer types (like `read`, that returns an `i64`)
    fn get_handle_and<F, T: From<i32>>(&mut self, fd: i32, f: F) -> InterpResult<'tcx, T>
    where
        F: Fn(&FileHandle) -> InterpResult<'tcx, T>,
    {
        let this = self.eval_context_mut();
        if let Some(handle) = this.machine.file_handler.handles.get(&fd) {
            f(handle)
        } else {
            this.machine.last_error = this.eval_libc_i32("EBADF")? as u32;
            Ok((-1).into())
        }
    }

    /// Helper function that removes a `FileHandle` and allows to manipulate it using the `f`
    /// closure. This function is quite useful when you need to modify a `FileHandle` but you need
    /// to modify `MiriEvalContext` at the same time, so you can modify the handle and reinsert it
    /// using `f`.
    ///
    /// If the `fd` file descriptor does not correspond to a file, this functions returns `Ok(-1)`
    /// and sets `Evaluator::last_error` to `libc::EBADF` (invalid file descriptor).
    ///
    /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
    /// functions return different integer types (like `read`, that returns an `i64`)
    fn remove_handle_and<F, T: From<i32>>(&mut self, fd: i32, mut f: F) -> InterpResult<'tcx, T>
    where
        F: FnMut(FileHandle, &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx, T>,
    {
        let this = self.eval_context_mut();
        if let Some(handle) = this.machine.file_handler.handles.remove(&fd) {
            f(handle, this)
        } else {
            this.machine.last_error = this.eval_libc_i32("EBADF")? as u32;
            Ok((-1).into())
        }
    }

    /// Helper function that consumes an `std::io::Result<T>` and returns an
    /// `InterpResult<'tcx,T>::Ok` instead. It is expected that the result can be converted to an
    /// OS error using `std::io::Error::raw_os_error`.
    ///
    /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
    /// functions return different integer types (like `read`, that returns an `i64`)
    fn consume_result<T: From<i32>>(&mut self, result: std::io::Result<T>) -> InterpResult<'tcx, T> {
        match result {
            Ok(ok) => Ok(ok),
            Err(e) => {
                self.eval_context_mut().machine.last_error = e.raw_os_error().unwrap() as u32;
                Ok((-1).into())
            }
        }
    }
}
<commit_msg>Avoid early return after handles are removed<commit_after>use std::collections::HashMap;
use std::fs::{File, OpenOptions};
use std::io::{Read, Write};

use rustc::ty::layout::Size;

use crate::stacked_borrows::Tag;
use crate::*;

pub struct FileHandle {
    file: File,
    flag: i32,
}

pub struct FileHandler {
    handles: HashMap<i32, FileHandle>,
    low: i32,
}

impl Default for FileHandler {
    fn default() -> Self {
        FileHandler {
            handles: Default::default(),
            // 0, 1 and 2 are reserved for stdin, stdout and stderr
            low: 3,
        }
    }
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn open(
        &mut self,
        path_op: OpTy<'tcx, Tag>,
        flag_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`open` not available when isolation is enabled")
        }

        let flag = this.read_scalar(flag_op)?.to_i32()?;

        let mut options = OpenOptions::new();

        // The first two bits of the flag correspond to the access mode of the file in linux.
        let access_mode = flag & 0b11;

        if access_mode == this.eval_libc_i32("O_RDONLY")? {
            options.read(true);
        } else if access_mode == this.eval_libc_i32("O_WRONLY")? {
            options.write(true);
        } else if access_mode == this.eval_libc_i32("O_RDWR")? {
            options.read(true).write(true);
        } else {
            throw_unsup_format!("Unsupported access mode {:#x}", access_mode);
        }

        if flag & this.eval_libc_i32("O_APPEND")? != 0 {
            options.append(true);
        }
        if flag & this.eval_libc_i32("O_TRUNC")? != 0 {
            options.truncate(true);
        }
        if flag & this.eval_libc_i32("O_CREAT")? != 0 {
            options.create(true);
        }

        let path_bytes = this
            .memory()
            .read_c_str(this.read_scalar(path_op)?.not_undef()?)?;
        let path = std::str::from_utf8(path_bytes)
            .map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", path_bytes))?;

        let fd = options.open(path).map(|file| {
            let mut fh = &mut this.machine.file_handler;
            fh.low += 1;
            fh.handles.insert(fh.low, FileHandle { file, flag });
            fh.low
        });

        this.consume_result(fd)
    }

    fn fcntl(
        &mut self,
        fd_op: OpTy<'tcx, Tag>,
        cmd_op: OpTy<'tcx, Tag>,
        arg_op: Option<OpTy<'tcx, Tag>>,
    ) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`fcntl` not available when isolation is enabled")
        }

        let fd = this.read_scalar(fd_op)?.to_i32()?;
        let cmd = this.read_scalar(cmd_op)?.to_i32()?;

        if cmd == this.eval_libc_i32("F_SETFD")? {
            // This does not affect the file itself. Certain flags might require changing the file
            // or the way it is accessed somehow.
            let flag = this.read_scalar(arg_op.unwrap())?.to_i32()?;
            // The only usage of this in stdlib at the moment is to enable the `FD_CLOEXEC` flag.
            let fd_cloexec = this.eval_libc_i32("FD_CLOEXEC")?;
            if let Some(FileHandle { flag: old_flag, .. }) =
                this.machine.file_handler.handles.get_mut(&fd)
            {
                if flag ^ *old_flag == fd_cloexec {
                    *old_flag = flag;
                } else {
                    throw_unsup_format!("Unsupported arg {:#x} for `F_SETFD`", flag);
                }
            }
            Ok(0)
        } else if cmd == this.eval_libc_i32("F_GETFD")? {
            this.get_handle_and(fd, |handle| Ok(handle.flag))
        } else {
            throw_unsup_format!("Unsupported command {:#x}", cmd);
        }
    }

    fn close(&mut self, fd_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`close` not available when isolation is enabled")
        }

        let fd = this.read_scalar(fd_op)?.to_i32()?;

        this.remove_handle_and(fd, |handle, this| {
            this.consume_result(handle.file.sync_all().map(|_| 0i32))
        })
    }

    fn read(
        &mut self,
        fd_op: OpTy<'tcx, Tag>,
        buf_op: OpTy<'tcx, Tag>,
        count_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i64> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`read` not available when isolation is enabled")
        }

        let tcx = &{ this.tcx.tcx };

        let fd = this.read_scalar(fd_op)?.to_i32()?;
        let buf = this.force_ptr(this.read_scalar(buf_op)?.not_undef()?)?;
        let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;

        // Remove the file handle to avoid borrowing issues
        this.remove_handle_and(fd, |mut handle, this| {
            // Don't use `?` to avoid returning before reinserting the handle
            let bytes = this
                .memory_mut()
                .get_mut(buf.alloc_id).and_then(|alloc|
                    alloc.get_bytes_mut(tcx, buf, Size::from_bytes(count))
                    .map(|buffer| handle.file.read(buffer).map(|bytes| bytes as i64))
                );
            // Reinsert the file handle
            this.machine.file_handler.handles.insert(fd, handle);
            this.consume_result(bytes?)
        })
    }

    fn write(
        &mut self,
        fd_op: OpTy<'tcx, Tag>,
        buf_op: OpTy<'tcx, Tag>,
        count_op: OpTy<'tcx, Tag>,
    ) -> InterpResult<'tcx, i64> {
        let this = self.eval_context_mut();

        if !this.machine.communicate {
            throw_unsup_format!("`write` not available when isolation is enabled")
        }

        let tcx = &{ this.tcx.tcx };

        let fd = this.read_scalar(fd_op)?.to_i32()?;
        let buf = this.force_ptr(this.read_scalar(buf_op)?.not_undef()?)?;
        let count = this.read_scalar(count_op)?.to_usize(&*this.tcx)?;

        this.remove_handle_and(fd, |mut handle, this| {
            let bytes = this.memory().get(buf.alloc_id).and_then(|alloc| {
                alloc
                    .get_bytes(tcx, buf, Size::from_bytes(count))
                    .map(|bytes| handle.file.write(bytes).map(|bytes| bytes as i64))
            });
            this.machine.file_handler.handles.insert(fd, handle);
            this.consume_result(bytes?)
        })
    }

    /// Helper function that gets a `FileHandle` immutable reference and allows to manipulate it
    /// using the `f` closure.
    ///
    /// If the `fd` file descriptor does not correspond to a file, this functions returns `Ok(-1)`
    /// and sets `Evaluator::last_error` to `libc::EBADF` (invalid file descriptor).
    ///
    /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
    /// functions return different integer types (like `read`, that returns an `i64`)
    fn get_handle_and<F, T: From<i32>>(&mut self, fd: i32, f: F) -> InterpResult<'tcx, T>
    where
        F: Fn(&FileHandle) -> InterpResult<'tcx, T>,
    {
        let this = self.eval_context_mut();
        if let Some(handle) = this.machine.file_handler.handles.get(&fd) {
            f(handle)
        } else {
            this.machine.last_error = this.eval_libc_i32("EBADF")? as u32;
            Ok((-1).into())
        }
    }

    /// Helper function that removes a `FileHandle` and allows to manipulate it using the `f`
    /// closure. This function is quite useful when you need to modify a `FileHandle` but you need
    /// to modify `MiriEvalContext` at the same time, so you can modify the handle and reinsert it
    /// using `f`.
    ///
    /// If the `fd` file descriptor does not correspond to a file, this functions returns `Ok(-1)`
    /// and sets `Evaluator::last_error` to `libc::EBADF` (invalid file descriptor).
    ///
    /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
    /// functions return different integer types (like `read`, that returns an `i64`)
    fn remove_handle_and<F, T: From<i32>>(&mut self, fd: i32, mut f: F) -> InterpResult<'tcx, T>
    where
        F: FnMut(FileHandle, &mut MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx, T>,
    {
        let this = self.eval_context_mut();
        if let Some(handle) = this.machine.file_handler.handles.remove(&fd) {
            f(handle, this)
        } else {
            this.machine.last_error = this.eval_libc_i32("EBADF")? as u32;
            Ok((-1).into())
        }
    }

    /// Helper function that consumes an `std::io::Result<T>` and returns an
    /// `InterpResult<'tcx,T>::Ok` instead. It is expected that the result can be converted to an
    /// OS error using `std::io::Error::raw_os_error`.
    ///
    /// This function uses `T: From<i32>` instead of `i32` directly because some IO related
    /// functions return different integer types (like `read`, that returns an `i64`)
    fn consume_result<T: From<i32>>(
        &mut self,
        result: std::io::Result<T>,
    ) -> InterpResult<'tcx, T> {
        match result {
            Ok(ok) => Ok(ok),
            Err(e) => {
                self.eval_context_mut().machine.last_error = e.raw_os_error().unwrap() as u32;
                Ok((-1).into())
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::sync as ssync;
use std::fmt;

mod mioco {
    pub use super::super::*;
}

/// MPSC channel modeled after `std::sync::mpsc`.
pub mod mpsc;

/// A reader-writer lock
///
/// Based on `std::sync::RwLock`. Calls `mioco::yield_now()` on contention.
#[derive(Debug)]
pub struct RwLock<T: ?Sized> {
    lock: ssync::RwLock<T>,
}

impl<T> RwLock<T> {
    /// Creates a new instance of an RwLock<T> which is unlocked.
    pub fn new(t: T) -> Self {
        RwLock { lock: ssync::RwLock::new(t) }
    }
}

impl<T: ?Sized> RwLock<T> {
    /// Get a reference to raw `std::sync::RwLock`.
    ///
    /// Use it to perform operations outside of mioco coroutines.
    pub fn native_lock(&self) -> &ssync::RwLock<T> {
        &self.lock
    }

    /// Locks this rwlock with shared read access, blocking the current
    /// coroutine until it can be acquired.
    pub fn read(&self) -> ssync::LockResult<ssync::RwLockReadGuard<T>> {
        loop {
            match self.lock.try_read() {
                Ok(guard) => return Ok(guard),
                Err(try_error) => {
                    match try_error {
                        ssync::TryLockError::Poisoned(p_err) => {
                            return Err(p_err);
                        }
                        ssync::TryLockError::WouldBlock => mioco::yield_now(),
                    }
                }
            }
        }
    }

    /// Attempts to acquire this rwlock with shared read access.
    pub fn try_read(&self) -> ssync::TryLockResult<ssync::RwLockReadGuard<T>> {
        self.lock.try_read()
    }

    /// Locks this rwlock with exclusive write access, blocking the current
    /// coroutine until it can be acquired.
    pub fn write(&self) -> ssync::LockResult<ssync::RwLockWriteGuard<T>> {
        loop {
            match self.lock.try_write() {
                Ok(guard) => return Ok(guard),
                Err(try_error) => {
                    match try_error {
                        ssync::TryLockError::Poisoned(p_err) => {
                            return Err(p_err);
                        }
                        ssync::TryLockError::WouldBlock => mioco::yield_now(),
                    }
                }
            }
        }
    }

    /// Attempts to lock this rwlock with exclusive write access.
    pub fn try_write(&self) -> ssync::TryLockResult<ssync::RwLockWriteGuard<T>> {
        self.lock.try_write()
    }

    /// Determines whether the lock is poisoned.
    pub fn is_poisoned(&self) -> bool {
        self.lock.is_poisoned()
    }
}

/// A Mutex
///
/// Based on `std::sync::Mutex`. Calls `mioco::yield_now()` on contention.
pub struct Mutex<T: ?Sized> {
    lock: ssync::Mutex<T>,
}

impl<T: ?Sized + fmt::Debug + 'static> fmt::Debug for Mutex<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.lock.fmt(f)
    }
}

impl<T> Mutex<T> {
    /// Creates a new instance of an Mutex<T> which is unlocked.
    pub fn new(t: T) -> Self {
        Mutex { lock: ssync::Mutex::new(t) }
    }
}

impl<T: ?Sized> Mutex<T> {
    /// Get a reference to raw `std::sync::Mutex`.
    ///
    /// Use it to perform operations outside of mioco coroutines.
    pub fn native_lock(&self) -> &ssync::Mutex<T> {
        &self.lock
    }

    /// Acquire a mutex, blocking the current coroutine until it is able to do so.
    pub fn lock(&self) -> ssync::LockResult<ssync::MutexGuard<T>> {
        loop {
            match self.try_lock() {
                Ok(guard) => return Ok(guard),
                Err(try_error) => {
                    match try_error {
                        ssync::TryLockError::Poisoned(p_err) => {
                            return Err(p_err);
                        }
                        ssync::TryLockError::WouldBlock => mioco::yield_now(),
                    }
                }
            }
        }
    }

    /// Attempt to acquire this lock.
    pub fn try_lock(&self) -> ssync::TryLockResult<ssync::MutexGuard<T>> {
        self.lock.try_lock()
    }
}
<commit_msg>RwLock and Mutex: make working outside of mioco.<commit_after>use std::sync as ssync;
use std::fmt;

mod mioco {
    pub use super::super::*;
}

/// MPSC channel modeled after `std::sync::mpsc`.
pub mod mpsc;

/// A reader-writer lock
///
/// Based on `std::sync::RwLock`. Calls `mioco::yield_now()` on contention.
///
/// Works both inside and outside of mioco.
#[derive(Debug)]
pub struct RwLock<T: ?Sized> {
    lock: ssync::RwLock<T>,
}

impl<T> RwLock<T> {
    /// Creates a new instance of an RwLock<T> which is unlocked.
    pub fn new(t: T) -> Self {
        RwLock { lock: ssync::RwLock::new(t) }
    }
}

impl<T: ?Sized> RwLock<T> {
    /// Get a reference to raw `std::sync::RwLock`.
    ///
    /// Use it to perform operations outside of mioco coroutines.
    pub fn native_lock(&self) -> &ssync::RwLock<T> {
        &self.lock
    }

    /// Locks this rwlock with shared read access, blocking the current
    /// coroutine until it can be acquired.
    pub fn read(&self) -> ssync::LockResult<ssync::RwLockReadGuard<T>> {
        if mioco::in_coroutine() {
            self.read_in_mioco()
        } else {
            self.lock.read()
        }
    }

    fn read_in_mioco(&self) -> ssync::LockResult<ssync::RwLockReadGuard<T>> {
        loop {
            match self.lock.try_read() {
                Ok(guard) => return Ok(guard),
                Err(try_error) => {
                    match try_error {
                        ssync::TryLockError::Poisoned(p_err) => {
                            return Err(p_err);
                        }
                        ssync::TryLockError::WouldBlock => mioco::yield_now(),
                    }
                }
            }
        }
    }

    /// Attempts to acquire this rwlock with shared read access.
    pub fn try_read(&self) -> ssync::TryLockResult<ssync::RwLockReadGuard<T>> {
        self.lock.try_read()
    }

    /// Locks this rwlock with exclusive write access, blocking the current
    /// coroutine until it can be acquired.
    pub fn write(&self) -> ssync::LockResult<ssync::RwLockWriteGuard<T>> {
        if mioco::in_coroutine() {
            self.write_in_mioco()
        } else {
            self.lock.write()
        }
    }

    fn write_in_mioco(&self) -> ssync::LockResult<ssync::RwLockWriteGuard<T>> {
        loop {
            match self.lock.try_write() {
                Ok(guard) => return Ok(guard),
                Err(try_error) => {
                    match try_error {
                        ssync::TryLockError::Poisoned(p_err) => {
                            return Err(p_err);
                        }
                        ssync::TryLockError::WouldBlock => mioco::yield_now(),
                    }
                }
            }
        }
    }

    /// Attempts to lock this rwlock with exclusive write access.
    pub fn try_write(&self) -> ssync::TryLockResult<ssync::RwLockWriteGuard<T>> {
        self.lock.try_write()
    }

    /// Determines whether the lock is poisoned.
    pub fn is_poisoned(&self) -> bool {
        self.lock.is_poisoned()
    }
}

/// A Mutex
///
/// Based on `std::sync::Mutex`.
///
/// Calls `mioco::yield_now()` on contention. (NOTE: Subject to potential change).
///
/// Works both inside and outside of mioco.
pub struct Mutex<T: ?Sized> {
    lock: ssync::Mutex<T>,
}

impl<T: ?Sized + fmt::Debug + 'static> fmt::Debug for Mutex<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.lock.fmt(f)
    }
}

impl<T> Mutex<T> {
    /// Creates a new instance of an Mutex<T> which is unlocked.
    pub fn new(t: T) -> Self {
        Mutex { lock: ssync::Mutex::new(t) }
    }
}

impl<T: ?Sized> Mutex<T> {
    /// Get a reference to raw `std::sync::Mutex`.
    ///
    /// Use it to perform operations outside of mioco coroutines.
    pub fn native_lock(&self) -> &ssync::Mutex<T> {
        &self.lock
    }

    /// Acquire a mutex, blocking the current coroutine until it is able to do so.
    pub fn lock(&self) -> ssync::LockResult<ssync::MutexGuard<T>> {
        if mioco::in_coroutine() {
            self.lock_in_mioco()
        } else {
            self.lock.lock()
        }
    }

    fn lock_in_mioco(&self) -> ssync::LockResult<ssync::MutexGuard<T>> {
        loop {
            match self.try_lock() {
                Ok(guard) => return Ok(guard),
                Err(try_error) => {
                    match try_error {
                        ssync::TryLockError::Poisoned(p_err) => {
                            return Err(p_err);
                        }
                        ssync::TryLockError::WouldBlock => mioco::yield_now(),
                    }
                }
            }
        }
    }

    /// Attempt to acquire this lock.
    pub fn try_lock(&self) -> ssync::TryLockResult<ssync::MutexGuard<T>> {
        self.lock.try_lock()
    }
}
<|endoftext|>