<commit_before>//! Initialization of the signed distance function near the level set.
use super::min;
use std;

/// Computes the signed distance function from a plane given as the _zero_ level set of a linear
/// function on a tetrahedron with 4 vertices with unit coordinates starting at (0, 0, 0) and
/// ending at (1, 1, 1), and in between exactly one coordinate changes from 0 to 1.
///
/// Inputs are `u`, the values at the vertices.
///
/// `perm[a]` specifies on which step the coordinate `a` changes. For example, the first coordinate
/// changes from vertex `perm[0]` to vertex `perm[0] + 1`.
///
/// The function returns the values of the (non-signed) distance function or `None` if the zero
/// level set does not pass through the tetrahedron.
pub fn tetrahedron_dist<F>(mut u: [f64; 4], mut dual_norm: F, perm: [usize; 3]) -> Option<[f64; 4]>
where
    F: FnMut([f64; 3]) -> f64,
{
    let mut n_pos = 0;
    let mut n_neg = 0;
    for u in &mut u {
        if *u > 0. {
            n_pos += 1;
        } else if *u < 0. {
            n_neg += 1;
        }
    }
    // check if sign differs (level set goes throught the triangle)
    if n_neg == 4 || n_pos == 4 {
        return None;
    }

    // everything is zero
    if n_neg + n_pos == 0 {
        return Some([0.; 4]);
    }

    let g = [u[1] - u[0], u[2] - u[1], u[3] - u[2]];
    let g = [g[perm[0]], g[perm[1]], g[perm[2]]];
    let g_norm_rcp = 1. / dual_norm(g);

    // FIXME: this requires for norm to be even
    // Support triangular anisotropies?
    for u in u.iter_mut() {
        *u = u.abs() * g_norm_rcp;
    }
    Some(u)
}

/// Initializes the distance around the free boundary.
///
/// Based on the level set function with values `u` given on a regular grid, it computes the
/// distance from the _zero_ level set in the nodes of the triangles through which the level set
/// passes.  Stores the result in the preallocated slice `d`.
///
/// Nodes away from the boundary have their value set to `std::f64::MAX`.
///
/// Splits every cube into six tetrahedra and computes the distance on each of them.
pub fn init_dist_3d<F>(d: &mut [f64], u: &[f64], dim: (usize, usize, usize), mut dual_norm: F)
where
    F: FnMut([f64; 3]) -> f64,
{
    let (ni, nj, nk) = dim;
    assert_eq!(ni * nj * nk, u.len());
    assert_eq!(ni * nj * nk, d.len());
    let (si, sj, sk) = (nj * nk, nk, 1);

    for d in &mut *d {
        *d = std::f64::MAX;
    }

    macro_rules! tetra {
        ($s:expr, [$pi:expr, $pj:expr, $pk:expr]) => {
            // $pi specifies at which step the i-th coordinate changes, etc.
            let offset = |step|
                            if $pi == step { si } else { 0 } +
                            if $pj == step { sj } else { 0 } +
                            if $pk == step { sk } else { 0 };

            let s0 = $s;
            let s1 = s0 - offset(0);
            let s2 = s1 - offset(1);
            let s3 = s2 - offset(2);
            let v = [u[s0], u[s1], u[s2], u[s3]];

            let r = tetrahedron_dist(v, &mut dual_norm, [$pi, $pj, $pk]);

            if let Some(r) = r {
                d[s0] = min(d[s0], r[0]);
                d[s1] = min(d[s1], r[1]);
                d[s2] = min(d[s2], r[2]);
                d[s3] = min(d[s3], r[3]);
            }
        };
    }

    for i in 1..ni {
        for j in 1..nj {
            let s = i * si + j * sj;
            let v = [u[s], u[s - si], u[s - sj], u[s - si - sj]];
            let mut all_pos_prev = v.iter().all(|&v| v > 0.);
            let mut all_neg_prev = v.iter().all(|&v| v < 0.);
            for k in 1..nk {
                let s = i * si + j * sj + k;
                let v = [u[s], u[s - si], u[s - sj], u[s - si - sj]];
                let mut all_pos = v.iter().all(|&v| v > 0.);
                let mut all_neg = v[0] < 0. && v[1] < 0. && v[2] < 0. && v[3] < 0.;

                if !((all_pos_prev && all_pos) || (all_neg_prev && all_neg)) {
                    tetra!(s, [0, 1, 2]);
                    tetra!(s, [0, 2, 1]);
                    tetra!(s, [1, 0, 2]);
                    tetra!(s, [2, 0, 1]);
                    tetra!(s, [1, 2, 0]);
                    tetra!(s, [2, 1, 0]);
                }
                all_pos_prev = all_pos;
                all_neg_prev = all_neg;
            }
        }
    }
}

/// Compute the anisotropic distance to the zero level set of a function on a axes-aligned
/// right triangle. The right angle is assumed to be at vertex 1.
///
/// `perm` specifies which leg of the triangle corresponds to the directions e₁ and e₂:
///
/// `[0, 1]`: 0-1 leg is parallel to e₁, 1-2 leg is parallel to e₂
/// `[1, 0]`: 0-1 leg is parallel to e₂, 1-2 leg is parallel to e₁
///
/// ```text
/// [0, 1]    [1, 0]
/// ------    ------
///
///     2      1--2
///    /|      | /
///   / |      |/
///  0--1      0
/// ```
///
fn triangle_dist<F>(mut u: [f64; 3], perm: [usize; 2], mut dual_norm: F) -> Option<[f64; 3]>
where
    F: FnMut([f64; 2]) -> f64,
{
    // check if sign differs (level set goes throught the triangle)
    if (u[0] > 0. && u[1] > 0. && u[2] > 0.) || (u[0] < 0. && u[1] < 0. && u[2] < 0.) {
        return None;
    }

    let g = [u[1] - u[0], u[2] - u[1]];
    let g = [g[perm[0]], g[perm[1]]];
    let norm = dual_norm(g);
    // all values are zero
    if norm == 0. {
        return Some([0., 0., 0.]);
    }
    let g_norm_rcp = 1. / norm;

    // TODO: This supports only even norms. Do we want to support triangle norms, for instance?
    for u in u.iter_mut() {
        *u = u.abs() * g_norm_rcp;
    }
    Some(u)
}

/// As `init_dist_2d`, but for general anisotropic norm.
///
/// `dual_norm` is the __dual__ norm. It must be a positively one-homogeneous function.
pub fn init_dist_2d<F>(d: &mut [f64], u: &[f64], dim: (usize, usize), mut dual_norm: F)
where
    F: FnMut([f64; 2]) -> f64,
{
    let (nx, ny) = dim;
    assert_eq!(nx * ny, u.len());
    assert_eq!(nx * ny, d.len());

    for d in &mut *d {
        *d = std::f64::MAX;
    }

    for j in 1..nx {
        for i in 1..ny {
            let s = j * ny + i;
            let v = [s - ny - 1, s - ny, s];
            let r = triangle_dist([u[v[0]], u[v[1]], u[v[2]]], [1, 0], &mut dual_norm);
            if let Some(e) = r {
                for i in 0..3 {
                    d[v[i]] = min(e[i], d[v[i]]);
                }
            }
            let v = [s - ny - 1, s - 1, s];
            let r = triangle_dist([u[v[0]], u[v[1]], u[v[2]]], [0, 1], &mut dual_norm);
            if let Some(e) = r {
                for i in 0..3 {
                    d[v[i]] = min(e[i], d[v[i]]);
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::norm::{DualNorm, EuclideanNorm};

    #[test]
    fn simple_triangles() {
        let eucl_triangle_dist = |v| triangle_dist(v, [0, 1], |p| EuclideanNorm.dual_norm(p));
        assert_eq!(eucl_triangle_dist([0., 0., 0.]), Some([0., 0., 0.]));
        assert_eq!(eucl_triangle_dist([1., 1., 1.]), None);
        assert_eq!(eucl_triangle_dist([-1., -1., -1.]), None);
        assert_eq!(
            eucl_triangle_dist([0., 1., 0.]),
            Some([0., 1. / (2f64).sqrt(), 0.])
        );
        assert_eq!(eucl_triangle_dist([0., -1., -1.]), Some([0., 1., 1.]));
        assert_eq!(eucl_triangle_dist([0., 1., 1.]), Some([0., 1., 1.]));
        assert_eq!(eucl_triangle_dist([1., 1., 0.]), Some([1., 1., 0.]));
        assert_eq!(eucl_triangle_dist([-1., 0., 0.]), Some([1., 0., 0.]));
        assert_eq!(
            eucl_triangle_dist([1., 0., 1.]),
            Some([1. / (2f64).sqrt(), 0., 1. / (2f64).sqrt()])
        );
    }

    #[test]
    fn anisotropic_norm_2d() {
        // Du = (1, 0)
        let u = [0., 0., 1., 1.];
        let mut d = [0.; 4];
        init_dist_2d(&mut d, &u, (2, 2), |p| p[0].abs().max(2. * p[1].abs()));

        assert_eq!(d, [0., 0., 1., 1.]);

        // Du = (0, 1)
        let u = [0., 1., 0., 1.];
        let mut d = [0.; 4];
        init_dist_2d(&mut d, &u, (2, 2), |p| p[0].abs().max(2. * p[1].abs()));

        assert_eq!(d, [0., 0.5, 0., 0.5]);
    }

    #[test]
    fn anisotropic_norm_3d() {
        // Du = (1, 0, 0)
        let u = [0., 0., 0., 0., 1., 1., 1., 1.];
        let mut d = [0.; 8];
        init_dist_3d(&mut d, &u, (2, 2, 2), |p| {
            p[0].abs().max(2. * p[1].abs()).max(4. * p[2].abs())
        });

        assert_eq!(d, [0., 0., 0., 0., 1., 1., 1., 1.]);

        // Du = (0, 1, 0)
        let u = [0., 0., 1., 1., 0., 0., 1., 1.];
        let mut d = [0.; 8];
        init_dist_3d(&mut d, &u, (2, 2, 2), |p| {
            p[0].abs().max(2. * p[1].abs()).max(4. * p[2].abs())
        });

        assert_eq!(d, [0., 0., 0.5, 0.5, 0., 0., 0.5, 0.5]);

        // Du = (0, 0, 1)
        let u = [0., 1., 0., 1., 0., 1., 0., 1.];
        let mut d = [0.; 8];
        init_dist_3d(&mut d, &u, (2, 2, 2), |p| {
            p[0].abs().max(2. * p[1].abs()).max(4. * p[2].abs())
        });

        assert_eq!(d, [0., 0.25, 0., 0.25, 0., 0.25, 0., 0.25]);
    }
}
<commit_msg>Simplify tetrahedron_dist logic<commit_after>//! Initialization of the signed distance function near the level set.
use super::min;
use std;

/// Computes the signed distance function from a plane given as the _zero_ level set of a linear
/// function on a tetrahedron with 4 vertices with unit coordinates starting at (0, 0, 0) and
/// ending at (1, 1, 1), and in between exactly one coordinate changes from 0 to 1.
///
/// Inputs are `u`, the values at the vertices.
///
/// `perm[a]` specifies on which step the coordinate `a` changes. For example, the first coordinate
/// changes from vertex `perm[0]` to vertex `perm[0] + 1`.
///
/// The function returns the values of the (non-signed) distance function or `None` if the zero
/// level set does not pass through the tetrahedron.
#[inline(always)]
pub fn tetrahedron_dist<F>(mut u: [f64; 4], mut dual_norm: F, perm: [usize; 3]) -> Option<[f64; 4]>
where
    F: FnMut([f64; 3]) -> f64,
{
    // iterator is a bit slower
    if (u[0] > 0. && u[1] > 0. && u[2] > 0. && u[3] > 0.)
        || (u[0] < 0. && u[1] < 0. && u[2] < 0. && u[3] < 0.)
    {
        return None;
    }

    let g = [u[1] - u[0], u[2] - u[1], u[3] - u[2]];
    let g = [g[perm[0]], g[perm[1]], g[perm[2]]];
    let norm = dual_norm(g);
    // everything is zero
    if norm == 0. {
        return Some([0.; 4]);
    }
    let g_norm_rcp = 1. / norm;

    // FIXME: this requires for norm to be even
    // Support triangular anisotropies?
    for u in u.iter_mut() {
        *u = u.abs() * g_norm_rcp;
    }
    Some(u)
}

/// Initializes the distance function near the free boundary.
///
/// Splits every cube into six tetrahedra. Based on the level set function with values `u` given
/// on a regular grid, it computes the distance from the _zero_ level set in the nodes of the
/// tetrahedra through which the level set passes.  Stores the minimal value of the distance in the
/// preallocated slice `d`.
///
/// Nodes away from the boundary have their value set to `std::f64::MAX`.
///
/// `dual_norm` is the __dual__ norm. It must be an __even__ positively one-homogeneous function,
/// zero only at the origin.
pub fn init_dist_3d<F>(d: &mut [f64], u: &[f64], dim: (usize, usize, usize), mut dual_norm: F)
where
    F: FnMut([f64; 3]) -> f64,
{
    let (ni, nj, nk) = dim;
    assert_eq!(ni * nj * nk, u.len());
    assert_eq!(ni * nj * nk, d.len());
    let (si, sj, sk) = (nj * nk, nk, 1);

    for d in &mut *d {
        *d = std::f64::MAX;
    }

    macro_rules! tetra {
        ($s:expr, [$pi:expr, $pj:expr, $pk:expr]) => {
            // $pi specifies at which step the i-th coordinate changes, etc.
            let offset = |step|
                                        if $pi == step { si } else { 0 } +
                                        if $pj == step { sj } else { 0 } +
                                        if $pk == step { sk } else { 0 };

            let s0 = $s;
            let s1 = s0 - offset(0);
            let s2 = s1 - offset(1);
            let s3 = s2 - offset(2);
            let v = [u[s0], u[s1], u[s2], u[s3]];

            let r = tetrahedron_dist(v, &mut dual_norm, [$pi, $pj, $pk]);

            if let Some(r) = r {
                d[s0] = min(d[s0], r[0]);
                d[s1] = min(d[s1], r[1]);
                d[s2] = min(d[s2], r[2]);
                d[s3] = min(d[s3], r[3]);
            }
        };
    }

    for i in 1..ni {
        for j in 1..nj {
            let s = i * si + j * sj;
            let v = [u[s], u[s - si], u[s - sj], u[s - si - sj]];
            let mut all_pos_prev = v.iter().all(|&v| v > 0.);
            let mut all_neg_prev = v.iter().all(|&v| v < 0.);
            for k in 1..nk {
                let s = i * si + j * sj + k;
                let v = [u[s], u[s - si], u[s - sj], u[s - si - sj]];
                let mut all_pos = v.iter().all(|&v| v > 0.);
                let mut all_neg = v[0] < 0. && v[1] < 0. && v[2] < 0. && v[3] < 0.;

                if !((all_pos_prev && all_pos) || (all_neg_prev && all_neg)) {
                    tetra!(s, [0, 1, 2]);
                    tetra!(s, [0, 2, 1]);
                    tetra!(s, [1, 0, 2]);
                    tetra!(s, [2, 0, 1]);
                    tetra!(s, [1, 2, 0]);
                    tetra!(s, [2, 1, 0]);
                }
                all_pos_prev = all_pos;
                all_neg_prev = all_neg;
            }
        }
    }
}

/// Compute the anisotropic distance to the zero level set of a function on a axes-aligned
/// right triangle. The right angle is assumed to be at vertex 1.
///
/// `perm` specifies which leg of the triangle corresponds to the directions e₁ and e₂:
///
/// `[0, 1]`: 0-1 leg is parallel to e₁, 1-2 leg is parallel to e₂
/// `[1, 0]`: 0-1 leg is parallel to e₂, 1-2 leg is parallel to e₁
///
/// ```text
/// [0, 1]    [1, 0]
/// ------    ------
///
///     2      1--2
///    /|      | /
///   / |      |/
///  0--1      0
/// ```
///
fn triangle_dist<F>(mut u: [f64; 3], perm: [usize; 2], mut dual_norm: F) -> Option<[f64; 3]>
where
    F: FnMut([f64; 2]) -> f64,
{
    // check if sign differs (level set goes throught the triangle)
    if (u[0] > 0. && u[1] > 0. && u[2] > 0.) || (u[0] < 0. && u[1] < 0. && u[2] < 0.) {
        return None;
    }

    let g = [u[1] - u[0], u[2] - u[1]];
    let g = [g[perm[0]], g[perm[1]]];
    let norm = dual_norm(g);
    // all values are zero
    if norm == 0. {
        return Some([0., 0., 0.]);
    }
    let g_norm_rcp = 1. / norm;

    // TODO: This supports only even norms. Do we want to support triangle norms, for instance?
    for u in u.iter_mut() {
        *u = u.abs() * g_norm_rcp;
    }
    Some(u)
}

/// Initializes the distance function near the free boundary.
///
/// Splits every square into two triangles. Based on the level set function with values `u` given
/// on a regular grid, it computes the distance from the _zero_ level set in the nodes of the
/// triangle through which the level set passes.  Stores the minimal value of the distance in the
/// preallocated slice `d`.
///
/// Nodes away from the boundary have their value set to `std::f64::MAX`.
///
/// `dual_norm` is the __dual__ norm. It must be an __even__ positively one-homogeneous function,
/// zero only at the origin.
pub fn init_dist_2d<F>(d: &mut [f64], u: &[f64], dim: (usize, usize), mut dual_norm: F)
where
    F: FnMut([f64; 2]) -> f64,
{
    let (nx, ny) = dim;
    assert_eq!(nx * ny, u.len());
    assert_eq!(nx * ny, d.len());

    for d in &mut *d {
        *d = std::f64::MAX;
    }

    for j in 1..nx {
        for i in 1..ny {
            let s = j * ny + i;
            let v = [s - ny - 1, s - ny, s];
            let r = triangle_dist([u[v[0]], u[v[1]], u[v[2]]], [1, 0], &mut dual_norm);
            if let Some(e) = r {
                for i in 0..3 {
                    d[v[i]] = min(e[i], d[v[i]]);
                }
            }
            let v = [s - ny - 1, s - 1, s];
            let r = triangle_dist([u[v[0]], u[v[1]], u[v[2]]], [0, 1], &mut dual_norm);
            if let Some(e) = r {
                for i in 0..3 {
                    d[v[i]] = min(e[i], d[v[i]]);
                }
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::norm::{DualNorm, EuclideanNorm};

    #[test]
    fn simple_triangles() {
        let eucl_triangle_dist = |v| triangle_dist(v, [0, 1], |p| EuclideanNorm.dual_norm(p));
        assert_eq!(eucl_triangle_dist([0., 0., 0.]), Some([0., 0., 0.]));
        assert_eq!(eucl_triangle_dist([1., 1., 1.]), None);
        assert_eq!(eucl_triangle_dist([-1., -1., -1.]), None);
        assert_eq!(
            eucl_triangle_dist([0., 1., 0.]),
            Some([0., 1. / (2f64).sqrt(), 0.])
        );
        assert_eq!(eucl_triangle_dist([0., -1., -1.]), Some([0., 1., 1.]));
        assert_eq!(eucl_triangle_dist([0., 1., 1.]), Some([0., 1., 1.]));
        assert_eq!(eucl_triangle_dist([1., 1., 0.]), Some([1., 1., 0.]));
        assert_eq!(eucl_triangle_dist([-1., 0., 0.]), Some([1., 0., 0.]));
        assert_eq!(
            eucl_triangle_dist([1., 0., 1.]),
            Some([1. / (2f64).sqrt(), 0., 1. / (2f64).sqrt()])
        );
    }

    #[test]
    fn anisotropic_norm_2d() {
        // Du = (1, 0)
        let u = [0., 0., 1., 1.];
        let mut d = [0.; 4];
        init_dist_2d(&mut d, &u, (2, 2), |p| p[0].abs().max(2. * p[1].abs()));

        assert_eq!(d, [0., 0., 1., 1.]);

        // Du = (0, 1)
        let u = [0., 1., 0., 1.];
        let mut d = [0.; 4];
        init_dist_2d(&mut d, &u, (2, 2), |p| p[0].abs().max(2. * p[1].abs()));

        assert_eq!(d, [0., 0.5, 0., 0.5]);
    }

    #[test]
    fn anisotropic_norm_3d() {
        // Du = (1, 0, 0)
        let u = [0., 0., 0., 0., 1., 1., 1., 1.];
        let mut d = [0.; 8];
        init_dist_3d(&mut d, &u, (2, 2, 2), |p| {
            p[0].abs().max(2. * p[1].abs()).max(4. * p[2].abs())
        });

        assert_eq!(d, [0., 0., 0., 0., 1., 1., 1., 1.]);

        // Du = (0, 1, 0)
        let u = [0., 0., 1., 1., 0., 0., 1., 1.];
        let mut d = [0.; 8];
        init_dist_3d(&mut d, &u, (2, 2, 2), |p| {
            p[0].abs().max(2. * p[1].abs()).max(4. * p[2].abs())
        });

        assert_eq!(d, [0., 0., 0.5, 0.5, 0., 0., 0.5, 0.5]);

        // Du = (0, 0, 1)
        let u = [0., 1., 0., 1., 0., 1., 0., 1.];
        let mut d = [0.; 8];
        init_dist_3d(&mut d, &u, (2, 2, 2), |p| {
            p[0].abs().max(2. * p[1].abs()).max(4. * p[2].abs())
        });

        assert_eq!(d, [0., 0.25, 0., 0.25, 0., 0.25, 0., 0.25]);
    }
}
<|endoftext|>


<commit_before>use term_painter::ToStyle;
use term_painter::Color::*;
use std::io;

mod types;

// Game logic (board, initialization, valid move, set, play or finished)

/// Visualization of the boards.
fn print_boards(board1: &Vec<types::SubField>, board2: &Vec<types::SubField>) {
    println!("{}{}", "------------------ O W N   B O A R D ------------------",
        "------------------------- O P P O N E N T ----------------");

    let mut cnt = 9;

    for i in 0..10 {
        println!("");
        print!("{}  ", cnt);
        for j in 0..10 {
            if board1[j + i * 10] == types::SubField::Hit {
                print!(" {} ", Red.paint(board1[j + i * 10]));
            } else {
                print!(" {} ", board1[j + i * 10]);
            }
        }
        print!("        ");
        print!("{}  ", cnt);
        for j in 0..10 {
            if board2[j + i * 10] == types::SubField::Hit {
                print!(" {} ", Green.paint(board2[j + i * 10]));
            } else {
                print!(" {} ", board2[j + i * 10]);
            }
        }
        println!("");
        cnt -= 1;
    }
    println!("");
    println!("{}{}", "     A    B    C    D    E    F    G    H    I    J",
        "               A    B    C    D    E    F    G    H    I    J");
    println!("");
    println!("{}{}", "----------------------------------------------------",
        "--------------------------------------------------------------");
}

/// Reads a string from the terminal / user.
fn read_string() -> String {
    let mut buffer = String::new();
    io::stdin()
        .read_line(&mut buffer)
        .expect("something went horribly wrong...");

    /* Discard trailing newline */
    let new_len = buffer.trim_right().len();
    buffer.truncate(new_len);

    buffer
}

/// The actual placement of the ships.
fn place(player: &mut types::Player, ship: &types::ShipType) -> u8 {

    /* Vector to collect the indices for the possible ship position. */
    let mut indices = Vec::new();

    /* 100 --> invalid value */
    let mut input = 100;
    while input == 100 {
        input = get_input();
        match player.own_board[input] {
            types::SubField::Water => { indices.push(input); },
            _ => {
                println!("Invalid input, again please.");
                input = 100;
            },
        }
    }

    println!("{}{}", "Enter 'h' for a horizontal (upwards) orientation of the ship,",
        "'v' for a vertical (rightwards) one.");
    /* x --> invalid value */
    let mut orientation = "x".to_string();
    while orientation == "x" {
        orientation = read_string();
        if orientation != "h" && orientation != "v" {
            println!("Invalid input, again please.");
            orientation = "x".to_string();
        }
    }

    if orientation == "v" {
        for _ in 0..ship.size - 1 {
            /* Check to prevent out of bounds errors. */
            if input >= 10 {
                input -= 10;
            }
            if player.own_board[input] != types::SubField::Water
                /* input < 10 --> no field above */
                || input < 10 {
                    println!("Invalid position for this ship.");
                    println!("Please choose another coordinate.");
                    return 1
            }
            indices.push(input);
        }
    } else {
        for _ in 0..ship.size - 1 {
            /* Check to prevent out of bounds errors. */
            if input < 99 {
                input += 1;
            }
            if player.own_board[input] != types::SubField::Water
                /* unit position == 9 --> no field to the right */
                || (input % 10) == 9 {
                    println!("Invalid position for this ship.");
                    println!("Please choose another coordinate.");
                    return 1
            }
            indices.push(input);
        }
    }

    /* Places the ships on the board. */
    for i in indices.iter() {
        player.own_board[*i] = types::SubField::Ship;
    }

    0
}

/// Handles the initial ship placement for each player.
fn place_ships(mut player1: &mut types::Player, mut player2: &mut types::Player) {

    /* A vector of all the ships each player needs to place.
       The default version: #  Class of ship Size
                            1   Carrier       5
                            2   Battleship    4
                            3   Cruiser       3
                            4   Submarine     3
                            5   Destroyer     2
    */
    let s1 = types::ShipType{ name: "Carrier".to_string(), size: 5, amount: 1 };
    let s2 = types::ShipType{ name: "Battleship".to_string(), size: 4, amount: 2 };
    let s3 = types::ShipType{ name: "Cruiser".to_string(), size: 3, amount: 3 };
    let s4 = types::ShipType{ name: "Submarine".to_string(), size: 3, amount: 4 };
    let s5 = types::ShipType{ name: "Destroyer".to_string(), size: 2, amount: 5 };
    let ships = vec![s1, s2, s3, s4, s5];

    print_boards(&player1.own_board, &player1.op_board);

    /* Error code, should be replaced by proper error handling later. */
    let mut err;

    /* Asks player1 to place the ships. */
    for i in ships.iter() {
        for _ in 0..i.amount {
            err = 1;
            while err == 1 {
                println!("{}, please enter the first coordinate for your {:?}.", player1.name, i.name);
                err = place(&mut player1, i);
                player1.capacity += i.size;
                print_boards(&player1.own_board, &player1.op_board);
            }
        }
    }

    /* Asks player2 to place the ships. */
    for i in ships.iter() {
        for _ in 0..i.amount {
            err = 1;
            while err == 1 {
                println!("{}, please enter the first coordinate for your {:?}.", player2.name, i.name);
                err = place(&mut player2, i);
                player2.capacity += i.size;
                print_boards(&player2.own_board, &player2.op_board);
            }
        }
    }
}

/// Reads the coordinates of a field from the user
/// and returns the corresponding index.
fn get_input() -> usize {

    /* 100 --> invalid */
    let mut input = 100;

    while input == 100 {
        input = match read_string().as_ref() {
            "A0" => 90, "A1" => 80,"A2" => 70, "A3" => 60, "A4" => 50,
            "A5" => 40, "A6" => 30, "A7" => 20, "A8" => 10, "A9" => 0,
            "B0" => 91, "B1" => 81, "B2" => 71, "B3" => 61, "B4" => 51,
            "B5" => 41, "B6" => 31, "B7" => 21, "B8" => 11, "B9" => 1,
            "C0" => 92, "C1" => 82, "C2" => 72, "C3" => 62, "C4" => 52,
            "C5" => 42, "C6" => 32, "C7" => 22, "C8" => 12, "C9" => 2,
            "D0" => 93, "D1" => 83, "D2" => 73, "D3" => 63, "D4" => 53,
            "D5" => 43, "D6" => 33, "D7" => 23, "D8" => 13, "D9" => 3,
            "E0" => 94, "E1" => 84, "E2" => 74, "E3" => 64, "E4" => 54,
            "E5" => 44, "E6" => 34, "E7" => 24, "E8" => 14, "E9" => 4,
            "F0" => 95, "F1" => 85, "F2" => 75, "F3" => 65, "F4" => 55,
            "F5" => 45, "F6" => 35, "F7" => 25, "F8" => 15, "F9" => 5,
            "G0" => 96, "G1" => 86, "G2" => 76, "G3" => 66, "G4" => 56,
            "G5" => 46, "G6" => 36, "G7" => 26, "G8" => 16, "G9" => 6,
            "H0" => 97, "H1" => 87, "H2" => 77, "H3" => 67, "H4" => 57,
            "H5" => 47, "H6" => 37, "H7" => 27, "H8" => 17, "H9" => 7,
            "I0" => 98, "I1" => 88, "I2" => 78, "I3" => 68, "I4" => 58,
            "I5" => 48, "I6" => 38, "I7" => 28, "I8" => 18, "I9" => 8,
            "J0" => 99, "J1" => 89, "J2" => 79, "J3" => 69, "J4" => 59,
            "J5" => 49, "J6" => 39, "J7" => 29, "J8" => 19, "J9" => 9,
            _ => 100,
        };

        if input == 100 {
            println!("Invalid field, try again.")
        }
    }
    input
}

fn match_move(first: &mut types::Player, second: &mut types::Player, idx: usize) {

    match second.own_board[idx] {
        types::SubField::Water => {
            println!("Miss - try again.");
            first.op_board[idx] = types::SubField::WaterHit;
        }
        types::SubField::Ship => {
            println!("Hit!");
            first.op_board[idx] = types::SubField::Hit;
            second.own_board[idx] = types::SubField::Hit;
            second.capacity -= 1;
        },
        types::SubField::Hit => { println!("Already hit."); }
        types::SubField::WaterHit => { println!("Miss - try again."); }
    }
}

/// Lets the players perform their moves.
fn make_move(mut first: &mut types::Player, mut second: &mut types::Player) {
    println!("Enter coordinates, {}:", first.name);
    let input = get_input();
    match_move(&mut first, &mut second, input);
}

/// Returns whether all the player's ships got destroyed.
pub fn game_over(player: &types::Player) -> bool {
    player.capacity <= 0
}

pub fn start_match() {

    /* Creates the initial (empty) boards (10 x 10) for player1 and player2. */
    let mut player1 = types::Player {
        own_board: vec![types::SubField::Water; 100],
        op_board: vec![types::SubField::Water; 100],
        capacity: 0,
        name: "Player1".to_string(),
    };

    let mut player2 = types::Player {
        own_board: vec![types::SubField::Water; 100],
        op_board: vec![types::SubField::Water; 100],
        capacity: 0,
        name: "Player2".to_string(),
    };

    place_ships(&mut player1, &mut player2);

    loop {
        print_boards(&player1.own_board, &player1.op_board);
        make_move(&mut player1, &mut player2);
        if game_over(&player2) {
            println!("G A M E   O V E R");
            println!("Congratulations, Player1");
            break;
        }

        print_boards(&player2.own_board, &player2.op_board);
        make_move(&mut player2, &mut player1);
        if game_over(&player1) {
            println!("G A M E   O V E R");
            println!("Congratulations, Player2");
            break;
        }
    }
}
<commit_msg>fixed capacity bug<commit_after>use term_painter::ToStyle;
use term_painter::Color::*;
use std::io;

mod types;

// Game logic (board, initialization, valid move, set, play or finished)

/// Visualization of the boards.
fn print_boards(board1: &Vec<types::SubField>, board2: &Vec<types::SubField>) {
    println!("{}{}", "------------------ O W N   B O A R D ------------------",
        "------------------------- O P P O N E N T ----------------");

    let mut cnt = 9;

    for i in 0..10 {
        println!("");
        print!("{}  ", cnt);
        for j in 0..10 {
            if board1[j + i * 10] == types::SubField::Hit {
                print!(" {} ", Red.paint(board1[j + i * 10]));
            } else {
                print!(" {} ", board1[j + i * 10]);
            }
        }
        print!("        ");
        print!("{}  ", cnt);
        for j in 0..10 {
            if board2[j + i * 10] == types::SubField::Hit {
                print!(" {} ", Green.paint(board2[j + i * 10]));
            } else {
                print!(" {} ", board2[j + i * 10]);
            }
        }
        println!("");
        cnt -= 1;
    }
    println!("");
    println!("{}{}", "     A    B    C    D    E    F    G    H    I    J",
        "               A    B    C    D    E    F    G    H    I    J");
    println!("");
    println!("{}{}", "----------------------------------------------------",
        "--------------------------------------------------------------");
}

/// Reads a string from the terminal / user.
fn read_string() -> String {
    let mut buffer = String::new();
    io::stdin()
        .read_line(&mut buffer)
        .expect("something went horribly wrong...");

    /* Discard trailing newline */
    let new_len = buffer.trim_right().len();
    buffer.truncate(new_len);

    buffer
}

/// The actual placement of the ships.
fn place(player: &mut types::Player, ship: &types::ShipType) -> u8 {

    /* Vector to collect the indices for the possible ship position. */
    let mut indices = Vec::new();

    /* 100 --> invalid value */
    let mut input = 100;
    while input == 100 {
        input = get_input();
        match player.own_board[input] {
            types::SubField::Water => { indices.push(input); },
            _ => {
                println!("Invalid input, again please.");
                input = 100;
            },
        }
    }

    println!("{}{}", "Enter 'h' for a horizontal (upwards) orientation of the ship,",
        "'v' for a vertical (rightwards) one.");
    /* x --> invalid value */
    let mut orientation = "x".to_string();
    while orientation == "x" {
        orientation = read_string();
        if orientation != "h" && orientation != "v" {
            println!("Invalid input, again please.");
            orientation = "x".to_string();
        }
    }

    if orientation == "v" {
        for _ in 0..ship.size - 1 {
            /* Check to prevent out of bounds errors. */
            if input >= 10 {
                input -= 10;
            }
            if player.own_board[input] != types::SubField::Water
                /* input < 10 --> no field above */
                || input < 10 {
                    println!("Invalid position for this ship.");
                    println!("Please choose another coordinate.");
                    return 1
            }
            indices.push(input);
        }
    } else {
        for _ in 0..ship.size - 1 {
            /* Check to prevent out of bounds errors. */
            if input < 99 {
                input += 1;
            }
            if player.own_board[input] != types::SubField::Water
                /* unit position == 9 --> no field to the right */
                || (input % 10) == 9 {
                    println!("Invalid position for this ship.");
                    println!("Please choose another coordinate.");
                    return 1
            }
            indices.push(input);
        }
    }

    /* Places the ships on the board. */
    for i in indices.iter() {
        player.own_board[*i] = types::SubField::Ship;
    }

    0
}

/// Handles the initial ship placement for each player.
fn place_ships(mut player1: &mut types::Player, mut player2: &mut types::Player) {

    /* A vector of all the ships each player needs to place.
       The default version: #  Class of ship Size
                            1   Carrier       5
                            2   Battleship    4
                            3   Cruiser       3
                            4   Submarine     3
                            5   Destroyer     2
    */
    let s1 = types::ShipType{ name: "Carrier".to_string(), size: 5, amount: 1 };
    let s2 = types::ShipType{ name: "Battleship".to_string(), size: 4, amount: 2 };
    let s3 = types::ShipType{ name: "Cruiser".to_string(), size: 3, amount: 3 };
    let s4 = types::ShipType{ name: "Submarine".to_string(), size: 3, amount: 4 };
    let s5 = types::ShipType{ name: "Destroyer".to_string(), size: 2, amount: 5 };
    let ships = vec![s1, s2, s3, s4, s5];

    print_boards(&player1.own_board, &player1.op_board);

    /* Error code, should be replaced by proper error handling later. */
    let mut err;

    /* Asks player1 to place the ships. */
    for i in ships.iter() {
        for _ in 0..i.amount {
            err = 1;
            while err == 1 {
                println!("{}, please enter the first coordinate for your {:?}.",
                    player1.name, i.name);
                err = place(&mut player1, i);
            }
            player1.capacity += i.size;
            print_boards(&player1.own_board, &player1.op_board);
        }
    }

    /* Asks player2 to place the ships. */
    for i in ships.iter() {
        for _ in 0..i.amount {
            err = 1;
            while err == 1 {
                println!("{}, please enter the first coordinate for your {:?}.",
                    player2.name, i.name);
                err = place(&mut player2, i);
            }
            player2.capacity += i.size;
            print_boards(&player2.own_board, &player2.op_board);
        }
    }
}

/// Reads the coordinates of a field from the user
/// and returns the corresponding index.
fn get_input() -> usize {

    /* 100 --> invalid */
    let mut input = 100;

    while input == 100 {
        input = match read_string().as_ref() {
            "A0" => 90, "A1" => 80,"A2" => 70, "A3" => 60, "A4" => 50,
            "A5" => 40, "A6" => 30, "A7" => 20, "A8" => 10, "A9" => 0,
            "B0" => 91, "B1" => 81, "B2" => 71, "B3" => 61, "B4" => 51,
            "B5" => 41, "B6" => 31, "B7" => 21, "B8" => 11, "B9" => 1,
            "C0" => 92, "C1" => 82, "C2" => 72, "C3" => 62, "C4" => 52,
            "C5" => 42, "C6" => 32, "C7" => 22, "C8" => 12, "C9" => 2,
            "D0" => 93, "D1" => 83, "D2" => 73, "D3" => 63, "D4" => 53,
            "D5" => 43, "D6" => 33, "D7" => 23, "D8" => 13, "D9" => 3,
            "E0" => 94, "E1" => 84, "E2" => 74, "E3" => 64, "E4" => 54,
            "E5" => 44, "E6" => 34, "E7" => 24, "E8" => 14, "E9" => 4,
            "F0" => 95, "F1" => 85, "F2" => 75, "F3" => 65, "F4" => 55,
            "F5" => 45, "F6" => 35, "F7" => 25, "F8" => 15, "F9" => 5,
            "G0" => 96, "G1" => 86, "G2" => 76, "G3" => 66, "G4" => 56,
            "G5" => 46, "G6" => 36, "G7" => 26, "G8" => 16, "G9" => 6,
            "H0" => 97, "H1" => 87, "H2" => 77, "H3" => 67, "H4" => 57,
            "H5" => 47, "H6" => 37, "H7" => 27, "H8" => 17, "H9" => 7,
            "I0" => 98, "I1" => 88, "I2" => 78, "I3" => 68, "I4" => 58,
            "I5" => 48, "I6" => 38, "I7" => 28, "I8" => 18, "I9" => 8,
            "J0" => 99, "J1" => 89, "J2" => 79, "J3" => 69, "J4" => 59,
            "J5" => 49, "J6" => 39, "J7" => 29, "J8" => 19, "J9" => 9,
            _ => 100,
        };

        if input == 100 {
            println!("Invalid field, try again.")
        }
    }
    input
}

fn match_move(first: &mut types::Player, second: &mut types::Player, idx: usize) {

    match second.own_board[idx] {
        types::SubField::Water => {
            println!("Miss - try again.");
            first.op_board[idx] = types::SubField::WaterHit;
        }
        types::SubField::Ship => {
            println!("Hit!");
            first.op_board[idx] = types::SubField::Hit;
            second.own_board[idx] = types::SubField::Hit;
            second.capacity -= 1;
        },
        types::SubField::Hit => { println!("Already hit."); }
        types::SubField::WaterHit => { println!("Miss - try again."); }
    }
}

/// Lets the players perform their moves.
fn make_move(mut first: &mut types::Player, mut second: &mut types::Player) {
    println!("Enter coordinates, {}:", first.name);
    let input = get_input();
    match_move(&mut first, &mut second, input);
}

/// Returns whether all the player's ships got destroyed.
pub fn game_over(player: &types::Player) -> bool {
    player.capacity <= 0
}

pub fn start_match() {

    /* Creates the initial (empty) boards (10 x 10) for player1 and player2. */
    let mut player1 = types::Player {
        own_board: vec![types::SubField::Water; 100],
        op_board: vec![types::SubField::Water; 100],
        capacity: 0,
        name: "Player1".to_string(),
    };

    let mut player2 = types::Player {
        own_board: vec![types::SubField::Water; 100],
        op_board: vec![types::SubField::Water; 100],
        capacity: 0,
        name: "Player2".to_string(),
    };

    place_ships(&mut player1, &mut player2);

    loop {
        print_boards(&player1.own_board, &player1.op_board);
        make_move(&mut player1, &mut player2);
        if game_over(&player2) {
            println!("G A M E   O V E R");
            println!("Congratulations, Player1");
            break;
        }

        print_boards(&player2.own_board, &player2.op_board);
        make_move(&mut player2, &mut player1);
        if game_over(&player1) {
            println!("G A M E   O V E R");
            println!("Congratulations, Player2");
            break;
        }
    }
}
<|endoftext|>


<commit_before>extern crate arguments;
extern crate log;
extern crate random;
extern crate streamer;

use std::error::Error;
use std::path::PathBuf;
use streamer::{ErrorString, Result, System};

mod logger;

const USAGE: &'static str = "
Usage: streamer [options]

Options:
    --config <path>          Configuration file (required).

    --help                   Display this message.
";

macro_rules! ok(
    ($result:expr) => (match $result {
        Ok(result) => result,
        Err(error) => return Err(Box::new(error)),
    });
);

macro_rules! raise(
    ($message:expr) => (return Err(Box::new(ErrorString($message.to_string()))));
);

fn main() {
    logger::setup();
    start().unwrap_or_else(|error| fail(&*error));
}

fn start() -> Result<()> {
    let arguments = ok!(arguments::parse(std::env::args()));

    if arguments.get::<bool>("help").unwrap_or(false) {
        help();
    }

    let system = match arguments.get::<String>("config").map(|config| PathBuf::from(config)) {
        Some(ref config) => try!(System::new(config, &random::default().seed([69, 42]))),
        _ => raise!("a configuration file is required"),
    };

    for event in system.take(100) {
        println!("{}", event);
    }

    Ok(())
}

fn help() -> ! {
    println!("{}", USAGE.trim());
    std::process::exit(0);
}

fn fail(error: &Error) -> ! {
    use std::io::{stderr, Write};
    stderr().write_all(format!("Error: {}.\n", error).as_bytes()).unwrap();
    std::process::exit(1);
}
<commit_msg>A bit of refactoring<commit_after>extern crate arguments;
extern crate log;
extern crate random;
extern crate streamer;

use std::error::Error;
use std::path::PathBuf;
use streamer::{ErrorString, Result, System};

mod logger;

const USAGE: &'static str = "
Usage: streamer [options]

Options:
    --config <path>          Configuration file (required).

    --help                   Display this message.
";

macro_rules! raise(
    ($message:expr) => (return Err(Box::new(ErrorString($message.to_string()))));
);

macro_rules! ok(
    ($result:expr) => (match $result {
        Ok(result) => result,
        Err(error) => return Err(Box::new(error)),
    });
);

macro_rules! some(
    ($option:expr, $($arg:tt)*) => (match $option {
        Some(value) => value,
        _ => raise!($($arg)*),
    });
);

fn main() {
    logger::setup();
    start().unwrap_or_else(|error| fail(&*error));
}

fn start() -> Result<()> {
    let arguments = ok!(arguments::parse(std::env::args()));

    if arguments.get::<bool>("help").unwrap_or(false) {
        help();
    }

    let system = {
        let config = some!(arguments.get::<String>("config"), "a configuration file is required");
        try!(System::new(PathBuf::from(config), &random::default().seed([69, 42])))
    };

    for event in system.take(100) {
        println!("{}", event);
    }

    Ok(())
}

fn help() -> ! {
    println!("{}", USAGE.trim());
    std::process::exit(0);
}

fn fail(error: &Error) -> ! {
    use std::io::{stderr, Write};
    stderr().write_all(format!("Error: {}.\n", error).as_bytes()).unwrap();
    std::process::exit(1);
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Richard Diamond & contributors.
//
// This file is part of the Rust PPApi project.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::borrow::Cow;

use ffi;

use gles::{self, Context3d, TextureBuffer, TexFormat};
use ppb::{get_video_decoder_opt, VideoDecoderIf};

use super::{GenericResource, Resource, ResourceType, Callback, Code,
            CallbackArgs, StorageToArgsMapper};

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct VideoDecoder(GenericResource);
impl Resource for VideoDecoder {
    fn unwrap(&self) -> ffi::PP_Resource { self.0.unwrap() }
    fn type_of(&self) -> Option<ResourceType> { Some(ResourceType::VideoDecoder) }
}
#[doc(hidden)]
impl From<ffi::PP_Resource> for VideoDecoder {
    fn from(v: ffi::PP_Resource) -> VideoDecoder {
        VideoDecoder(From::from(v))
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum H264Profile {
    BaseLine,
    Main,
    Extended,
    High,
    High10,
    High422,
    High444Predictive,
    ScalableBaseLine,
    ScalableHigh,
    StereoHigh,
    MultiViewHigh,
}
#[doc(hidden)]
impl Into<ffi::PP_VideoProfile> for H264Profile {
    fn into(self) -> ffi::PP_VideoProfile {
        use self::H264Profile::*;
        match self {
            BaseLine => ffi::PP_VIDEOPROFILE_H264BASELINE,
            Main => ffi::PP_VIDEOPROFILE_H264MAIN,
            Extended => ffi::PP_VIDEOPROFILE_H264EXTENDED,
            High => ffi::PP_VIDEOPROFILE_H264HIGH,
            High10 => ffi::PP_VIDEOPROFILE_H264HIGH10PROFILE,
            High422 => ffi::PP_VIDEOPROFILE_H264HIGH422PROFILE,
            High444Predictive => ffi::PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE,
            ScalableBaseLine => ffi::PP_VIDEOPROFILE_H264SCALABLEBASELINE,
            ScalableHigh => ffi::PP_VIDEOPROFILE_H264SCALABLEHIGH,
            StereoHigh => ffi::PP_VIDEOPROFILE_H264STEREOHIGH,
            MultiViewHigh => ffi::PP_VIDEOPROFILE_H264MULTIVIEWHIGH,
        }
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum Profile {
    VP9,
    VP8,
    H264(H264Profile),
}
#[doc(hidden)]
impl Into<ffi::PP_VideoProfile> for Profile {
    fn into(self) -> ffi::PP_VideoProfile {
        use self::Profile::*;
        match self {
            H264(v) => v.into(),
            VP9 => ffi::PP_VIDEOPROFILE_VP9_ANY,
            VP8 => ffi::PP_VIDEOPROFILE_VP8_ANY,
        }
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum Acceleration {
    Hardware { with_fallback: bool },
    Software,
}
#[doc(hidden)]
impl Into<ffi::PP_HardwareAcceleration> for Acceleration {
    fn into(self) -> ffi::PP_HardwareAcceleration {
        match self {
            Acceleration::Hardware { with_fallback: false, } =>
                ffi::PP_HARDWAREACCELERATION_ONLY,
            Acceleration::Hardware { with_fallback: true,  } =>
                ffi::PP_HARDWAREACCELERATION_WITHFALLBACK,
            Acceleration::Software =>
                ffi::PP_HARDWAREACCELERATION_NONE,
        }
    }
}
impl Default for Acceleration {
    fn default() -> Acceleration { Acceleration::Hardware { with_fallback: true } }
}

pub struct Frame {
    pub tag: u32,
    texture: TextureBuffer,
    texture_target: gles::types::Enum,
    texture_size: super::Size,
    visible_rect: super::Rect,
}
impl Frame {
    pub fn format(&self) -> TexFormat { TexFormat::Rgba }
}
impl From<ffi::Struct_PP_VideoPicture> for Frame {
    fn from(raw: ffi::Struct_PP_VideoPicture) -> Frame {
        Frame {
            tag: raw.decode_id,
            texture: From::from(raw.texture_id),
            texture_target: From::from(raw.texture_target),
            texture_size: From::from(raw.texture_size),
            visible_rect: From::from(raw.visible_rect),
        }
    }
}
impl Into<ffi::Struct_PP_VideoPicture> for Frame {
    fn into(self) -> ffi::Struct_PP_VideoPicture {
        use gles::traits::Buffer;
        ffi::Struct_PP_VideoPicture {
            decode_id: self.tag,
            texture_id: self.texture.unwrap(),
            texture_target: self.texture_target,
            texture_size: self.texture_size.into(),
            visible_rect: self.visible_rect.into(),
        }
    }
}
impl VideoDecoder {
    pub fn initialize<F>(&self, g3d: Context3d, profile: Profile,
                     accel: Acceleration, callback: F) -> Code
        where F: Callback,
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.initialize(self.unwrap(), g3d.unwrap(), profile.into(),
                                        accel.into(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    /// PPAPI allocates it's own copy of the data before returning.
    pub fn decode<'a, F>(&self, decode_tag: u32, data: Cow<'a, [u8]>, callback: F) -> Code
        where F: Callback
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.decode(self.unwrap(), decode_tag,
                                    data.as_ref().len(), data.as_ref().as_ptr(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn flush<F>(&self, callback: F) -> Code where F: Callback {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.flush(self.unwrap(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn reset<F>(&self, callback: F) -> Code where F: Callback {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.reset(self.unwrap(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn get_picture<F>(&self, callback: F) -> Code<Frame>
        where F: CallbackArgs<Frame>
    {
        impl super::InPlaceInit for ffi::Struct_PP_VideoPicture { }
        fn arg_map(raw: ffi::Struct_PP_VideoPicture, _status: Code) -> Frame {
            From::from(raw)
        }
        get_video_decoder_opt()
            .map(move |i| {
                let raw: ffi::Struct_PP_VideoPicture = Default::default();
                let mapper = StorageToArgsMapper(arg_map);
                let cc = callback.to_ffi_callback(raw, mapper);
                let code = i.get_picture(self.unwrap(), cc.raw_args(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn recycle(&self, frame: Frame) {
        get_video_decoder_opt()
            .map(move |i| {
                let ffi: ffi::Struct_PP_VideoPicture =
                    frame.into();
                i.recycle_picture(self.unwrap(), &ffi)
            });
    }
}
<commit_msg>Add a debug check.<commit_after>// Copyright (c) 2014 Richard Diamond & contributors.
//
// This file is part of the Rust PPApi project.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::borrow::Cow;

use ffi;

use gles::{self, Context3d, TextureBuffer, TexFormat};
use ppb::{get_video_decoder_opt, VideoDecoderIf};

use super::{GenericResource, Resource, ResourceType, Callback, Code,
            CallbackArgs, StorageToArgsMapper};

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct VideoDecoder(GenericResource);
impl Resource for VideoDecoder {
    fn unwrap(&self) -> ffi::PP_Resource { self.0.unwrap() }
    fn type_of(&self) -> Option<ResourceType> { Some(ResourceType::VideoDecoder) }
}
#[doc(hidden)]
impl From<ffi::PP_Resource> for VideoDecoder {
    fn from(v: ffi::PP_Resource) -> VideoDecoder {
        debug_assert!(get_video_decoder().is(v));
        VideoDecoder(From::from(v))
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum H264Profile {
    BaseLine,
    Main,
    Extended,
    High,
    High10,
    High422,
    High444Predictive,
    ScalableBaseLine,
    ScalableHigh,
    StereoHigh,
    MultiViewHigh,
}
#[doc(hidden)]
impl Into<ffi::PP_VideoProfile> for H264Profile {
    fn into(self) -> ffi::PP_VideoProfile {
        use self::H264Profile::*;
        match self {
            BaseLine => ffi::PP_VIDEOPROFILE_H264BASELINE,
            Main => ffi::PP_VIDEOPROFILE_H264MAIN,
            Extended => ffi::PP_VIDEOPROFILE_H264EXTENDED,
            High => ffi::PP_VIDEOPROFILE_H264HIGH,
            High10 => ffi::PP_VIDEOPROFILE_H264HIGH10PROFILE,
            High422 => ffi::PP_VIDEOPROFILE_H264HIGH422PROFILE,
            High444Predictive => ffi::PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE,
            ScalableBaseLine => ffi::PP_VIDEOPROFILE_H264SCALABLEBASELINE,
            ScalableHigh => ffi::PP_VIDEOPROFILE_H264SCALABLEHIGH,
            StereoHigh => ffi::PP_VIDEOPROFILE_H264STEREOHIGH,
            MultiViewHigh => ffi::PP_VIDEOPROFILE_H264MULTIVIEWHIGH,
        }
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum Profile {
    VP9,
    VP8,
    H264(H264Profile),
}
#[doc(hidden)]
impl Into<ffi::PP_VideoProfile> for Profile {
    fn into(self) -> ffi::PP_VideoProfile {
        use self::Profile::*;
        match self {
            H264(v) => v.into(),
            VP9 => ffi::PP_VIDEOPROFILE_VP9_ANY,
            VP8 => ffi::PP_VIDEOPROFILE_VP8_ANY,
        }
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum Acceleration {
    Hardware { with_fallback: bool },
    Software,
}
#[doc(hidden)]
impl Into<ffi::PP_HardwareAcceleration> for Acceleration {
    fn into(self) -> ffi::PP_HardwareAcceleration {
        match self {
            Acceleration::Hardware { with_fallback: false, } =>
                ffi::PP_HARDWAREACCELERATION_ONLY,
            Acceleration::Hardware { with_fallback: true,  } =>
                ffi::PP_HARDWAREACCELERATION_WITHFALLBACK,
            Acceleration::Software =>
                ffi::PP_HARDWAREACCELERATION_NONE,
        }
    }
}
impl Default for Acceleration {
    fn default() -> Acceleration { Acceleration::Hardware { with_fallback: true } }
}

pub struct Frame {
    pub tag: u32,
    texture: TextureBuffer,
    texture_target: gles::types::Enum,
    texture_size: super::Size,
    visible_rect: super::Rect,
}
impl Frame {
    pub fn format(&self) -> TexFormat { TexFormat::Rgba }
}
impl From<ffi::Struct_PP_VideoPicture> for Frame {
    fn from(raw: ffi::Struct_PP_VideoPicture) -> Frame {
        Frame {
            tag: raw.decode_id,
            texture: From::from(raw.texture_id),
            texture_target: From::from(raw.texture_target),
            texture_size: From::from(raw.texture_size),
            visible_rect: From::from(raw.visible_rect),
        }
    }
}
impl Into<ffi::Struct_PP_VideoPicture> for Frame {
    fn into(self) -> ffi::Struct_PP_VideoPicture {
        use gles::traits::Buffer;
        ffi::Struct_PP_VideoPicture {
            decode_id: self.tag,
            texture_id: self.texture.unwrap(),
            texture_target: self.texture_target,
            texture_size: self.texture_size.into(),
            visible_rect: self.visible_rect.into(),
        }
    }
}
impl VideoDecoder {
    pub fn initialize<F>(&self, g3d: Context3d, profile: Profile,
                     accel: Acceleration, callback: F) -> Code
        where F: Callback,
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.initialize(self.unwrap(), g3d.unwrap(), profile.into(),
                                        accel.into(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    /// PPAPI allocates it's own copy of the data before returning.
    pub fn decode<'a, F>(&self, decode_tag: u32, data: Cow<'a, [u8]>, callback: F) -> Code
        where F: Callback
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.decode(self.unwrap(), decode_tag,
                                    data.as_ref().len(), data.as_ref().as_ptr(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn flush<F>(&self, callback: F) -> Code where F: Callback {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.flush(self.unwrap(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn reset<F>(&self, callback: F) -> Code where F: Callback {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.reset(self.unwrap(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn get_picture<F>(&self, callback: F) -> Code<Frame>
        where F: CallbackArgs<Frame>
    {
        impl super::InPlaceInit for ffi::Struct_PP_VideoPicture { }
        fn arg_map(raw: ffi::Struct_PP_VideoPicture, _status: Code) -> Frame {
            From::from(raw)
        }
        get_video_decoder_opt()
            .map(move |i| {
                let raw: ffi::Struct_PP_VideoPicture = Default::default();
                let mapper = StorageToArgsMapper(arg_map);
                let cc = callback.to_ffi_callback(raw, mapper);
                let code = i.get_picture(self.unwrap(), cc.raw_args(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn recycle(&self, frame: Frame) {
        get_video_decoder_opt()
            .map(move |i| {
                let ffi: ffi::Struct_PP_VideoPicture =
                    frame.into();
                i.recycle_picture(self.unwrap(), &ffi)
            });
    }
}
<|endoftext|>


<commit_before>use core::ops::{Range, RangeFull, RangeFrom, RangeTo, RangeInclusive};

// Test the Range structs without the syntactic sugar.

#[test]
fn test_range() {
    let r = Range { start: 2, end: 10 };
    let mut count = 0;
    for (i, ri) in r.enumerate() {
        assert!(ri == i + 2);
        assert!(ri >= 2 && ri < 10);
        count += 1;
    }
    assert!(count == 8);
}

#[test]
fn test_range_from() {
    let r = RangeFrom { start: 2 };
    let mut count = 0;
    for (i, ri) in r.take(10).enumerate() {
        assert!(ri == i + 2);
        assert!(ri >= 2 && ri < 12);
        count += 1;
    }
    assert!(count == 10);
}

#[test]
fn test_range_to() {
    // Not much to test.
    let _ = RangeTo { end: 42 };
}

#[test]
fn test_full_range() {
    // Not much to test.
    let _ = RangeFull;
}

#[test]
fn test_range_inclusive() {
    let mut r = RangeInclusive::new(1i8, 2);
    assert_eq!(r.next(), Some(1));
    assert_eq!(r.next(), Some(2));
    assert_eq!(r.next(), None);

    r = RangeInclusive::new(127i8, 127);
    assert_eq!(r.next(), Some(127));
    assert_eq!(r.next(), None);

    r = RangeInclusive::new(-128i8, -128);
    assert_eq!(r.next_back(), Some(-128));
    assert_eq!(r.next_back(), None);

    // degenerate
    r = RangeInclusive::new(1, -1);
    assert_eq!(r.size_hint(), (0, Some(0)));
    assert_eq!(r.next(), None);
}

#[test]
fn test_range_is_empty() {
    use core::f32::*;

    assert!(!(0.0 .. 10.0).is_empty());
    assert!( (-0.0 .. 0.0).is_empty());
    assert!( (10.0 .. 0.0).is_empty());

    assert!(!(NEG_INFINITY .. INFINITY).is_empty());
    assert!( (EPSILON .. NAN).is_empty());
    assert!( (NAN .. EPSILON).is_empty());
    assert!( (NAN .. NAN).is_empty());

    assert!(!(0.0 ..= 10.0).is_empty());
    assert!(!(-0.0 ..= 0.0).is_empty());
    assert!( (10.0 ..= 0.0).is_empty());

    assert!(!(NEG_INFINITY ..= INFINITY).is_empty());
    assert!( (EPSILON ..= NAN).is_empty());
    assert!( (NAN ..= EPSILON).is_empty());
    assert!( (NAN ..= NAN).is_empty());
}
<commit_msg>Improved test output for libcore/ops<commit_after>use core::ops::{Range, RangeFull, RangeFrom, RangeTo, RangeInclusive};

// Test the Range structs without the syntactic sugar.

#[test]
fn test_range() {
    let r = Range { start: 2, end: 10 };
    let mut count = 0;
    for (i, ri) in r.enumerate() {
        assert_eq!(ri, i + 2);
        assert!(ri >= 2 && ri < 10);
        count += 1;
    }
    assert_eq!(count, 8);
}

#[test]
fn test_range_from() {
    let r = RangeFrom { start: 2 };
    let mut count = 0;
    for (i, ri) in r.take(10).enumerate() {
        assert_eq!(ri, i + 2);
        assert!(ri >= 2 && ri < 12);
        count += 1;
    }
    assert_eq!(count, 10);
}

#[test]
fn test_range_to() {
    // Not much to test.
    let _ = RangeTo { end: 42 };
}

#[test]
fn test_full_range() {
    // Not much to test.
    let _ = RangeFull;
}

#[test]
fn test_range_inclusive() {
    let mut r = RangeInclusive::new(1i8, 2);
    assert_eq!(r.next(), Some(1));
    assert_eq!(r.next(), Some(2));
    assert_eq!(r.next(), None);

    r = RangeInclusive::new(127i8, 127);
    assert_eq!(r.next(), Some(127));
    assert_eq!(r.next(), None);

    r = RangeInclusive::new(-128i8, -128);
    assert_eq!(r.next_back(), Some(-128));
    assert_eq!(r.next_back(), None);

    // degenerate
    r = RangeInclusive::new(1, -1);
    assert_eq!(r.size_hint(), (0, Some(0)));
    assert_eq!(r.next(), None);
}

#[test]
fn test_range_is_empty() {
    use core::f32::*;

    assert!(!(0.0 .. 10.0).is_empty());
    assert!( (-0.0 .. 0.0).is_empty());
    assert!( (10.0 .. 0.0).is_empty());

    assert!(!(NEG_INFINITY .. INFINITY).is_empty());
    assert!( (EPSILON .. NAN).is_empty());
    assert!( (NAN .. EPSILON).is_empty());
    assert!( (NAN .. NAN).is_empty());

    assert!(!(0.0 ..= 10.0).is_empty());
    assert!(!(-0.0 ..= 0.0).is_empty());
    assert!( (10.0 ..= 0.0).is_empty());

    assert!(!(NEG_INFINITY ..= INFINITY).is_empty());
    assert!( (EPSILON ..= NAN).is_empty());
    assert!( (NAN ..= EPSILON).is_empty());
    assert!( (NAN ..= NAN).is_empty());
}
<|endoftext|>


<commit_before><commit_msg>Test some actual ignore caches<commit_after><|endoftext|>


<commit_before>use errors;

// see OSC Type Tag String: http://opensoundcontrol.org/spec-1_0
// padding: zero bytes (n*4)
pub enum OscType {
    OscInt(i32),
    OscFloat(f32),
    OscString(String), // padding
    OscBlob(Vec<u8>), // padding
    OscTimetag(u64),
    // nonstandard argument types
    // ignore them if not implemented
    OscInt64(i64), // big-endian
    OscDouble(u64),
    OscChar(u8), // padding
    OscColor(u32), // RGBA
    OscMidi(OscMidiType),
    OscTrue,
    OscFalse,
    OscNil,
    OscInf,
    OscArray(Vec<OscType>),
}

pub struct OscMidiType {
    port: u8,
    status: u8,
    data1: u8, // maybe use an enum for data?
    data2: u8,
}

/// An *osc packet* can contain an *osc message* or a bundle of nested messages
/// which is called *osc bundle*.
pub enum OscPacket {
    Message(OscMessage),
    Bundle(OscBundle),
}

pub struct OscMessage;
pub struct OscBundle;

pub type OscResult<T> = Result<T, errors::OscError>;<commit_msg>Fix value for `OscDouble`<commit_after>use errors;

// see OSC Type Tag String: http://opensoundcontrol.org/spec-1_0
// padding: zero bytes (n*4)
pub enum OscType {
    OscInt(i32),
    OscFloat(f32),
    OscString(String), // padding
    OscBlob(Vec<u8>), // padding
    OscTimetag(u64),
    // nonstandard argument types
    // ignore them if not implemented
    OscInt64(i64), // big-endian
    OscDouble(f64),
    OscChar(u8), // padding
    OscColor(u32), // RGBA
    OscMidi(OscMidiType),
    OscTrue,
    OscFalse,
    OscNil,
    OscInf,
    OscArray(Vec<OscType>),
}

pub struct OscMidiType {
    port: u8,
    status: u8,
    data1: u8, // maybe use an enum for data?
    data2: u8,
}

/// An *osc packet* can contain an *osc message* or a bundle of nested messages
/// which is called *osc bundle*.
pub enum OscPacket {
    Message(OscMessage),
    Bundle(OscBundle),
}

pub struct OscMessage;
pub struct OscBundle;

pub type OscResult<T> = Result<T, errors::OscError>;<|endoftext|>


<commit_before>use std::env;
use std::process::Command;
use std::str::{self, FromStr};

// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
    let minor = match rustc_minor_version() {
        Some(minor) => minor,
        None => return,
    };

    let target = env::var("TARGET").unwrap();
    let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";

    let has_atomic_integers = target_has_at_least_atomic_u64(&target);

    // std::collections::Bound was stabilized in Rust 1.17
    // but it was moved to core::ops later in Rust 1.26:
    // https://doc.rust-lang.org/core/ops/enum.Bound.html
    if minor >= 26 {
        println!("cargo:rustc-cfg=ops_bound");
    } else if minor >= 17 && cfg!(feature = "std") {
        println!("cargo:rustc-cfg=collections_bound");
    }

    // core::cmp::Reverse stabilized in Rust 1.19:
    // https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html
    if minor >= 19 {
        println!("cargo:rustc-cfg=core_reverse");
    }

    // CString::into_boxed_c_str stabilized in Rust 1.20:
    // https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
    if minor >= 20 {
        println!("cargo:rustc-cfg=de_boxed_c_str");
    }

    // From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
    // https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>>
    // https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>>
    if minor >= 21 {
        println!("cargo:rustc-cfg=de_rc_dst");
    }

    // Duration available in core since Rust 1.25:
    // https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations
    if minor >= 25 {
        println!("cargo:rustc-cfg=core_duration");
    }

    // 128-bit integers stabilized in Rust 1.26:
    // https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
    //
    // Disabled on Emscripten targets as Emscripten doesn't
    // currently support integers larger than 64 bits.
    if minor >= 26 && !emscripten {
        println!("cargo:rustc-cfg=integer128");
    }

    // Inclusive ranges methods stabilized in Rust 1.27:
    // https://github.com/rust-lang/rust/pull/50758
    if minor >= 27 {
        println!("cargo:rustc-cfg=range_inclusive");
    }

    // Non-zero integers stabilized in Rust 1.28:
    // https://github.com/rust-lang/rust/pull/50808
    if minor >= 28 {
        println!("cargo:rustc-cfg=num_nonzero");
    }

    if minor >= 34 && has_atomic_integers {
        println!("cargo:rustc-cfg=std_integer_atomics");
    }
}

fn rustc_minor_version() -> Option<u32> {
    let rustc = match env::var_os("RUSTC") {
        Some(rustc) => rustc,
        None => return None,
    };

    let output = match Command::new(rustc).arg("--version").output() {
        Ok(output) => output,
        Err(_) => return None,
    };

    let version = match str::from_utf8(&output.stdout) {
        Ok(version) => version,
        Err(_) => return None,
    };

    let mut pieces = version.split('.');
    if pieces.next() != Some("rustc 1") {
        return None;
    }

    let next = match pieces.next() {
        Some(next) => next,
        None => return None,
    };

    u32::from_str(next).ok()
}

fn target_has_at_least_atomic_u64(target: &str) -> bool {
    // The cfg variable target_has_atomic is unstable
    // so this data comes from the  src/librustc_target/spec/*.rs
    // files in the rust source. Generally, it's 64-bit platforms
    // plus i686.
    if target.starts_with("x86-64") || target.starts_with("i686") ||
        target.starts_with("aarch64") || target.starts_with("powerpc64") ||
        target.starts_with("sparc64") || target.starts_with("mips64el") {
        true
    } else {
        false
    }
}
<commit_msg>replaced one too many _ with -<commit_after>use std::env;
use std::process::Command;
use std::str::{self, FromStr};

// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
    let minor = match rustc_minor_version() {
        Some(minor) => minor,
        None => return,
    };

    let target = env::var("TARGET").unwrap();
    let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";

    let has_atomic_integers = target_has_at_least_atomic_u64(&target);

    // std::collections::Bound was stabilized in Rust 1.17
    // but it was moved to core::ops later in Rust 1.26:
    // https://doc.rust-lang.org/core/ops/enum.Bound.html
    if minor >= 26 {
        println!("cargo:rustc-cfg=ops_bound");
    } else if minor >= 17 && cfg!(feature = "std") {
        println!("cargo:rustc-cfg=collections_bound");
    }

    // core::cmp::Reverse stabilized in Rust 1.19:
    // https://doc.rust-lang.org/stable/core/cmp/struct.Reverse.html
    if minor >= 19 {
        println!("cargo:rustc-cfg=core_reverse");
    }

    // CString::into_boxed_c_str stabilized in Rust 1.20:
    // https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
    if minor >= 20 {
        println!("cargo:rustc-cfg=de_boxed_c_str");
    }

    // From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
    // https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>>
    // https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>>
    if minor >= 21 {
        println!("cargo:rustc-cfg=de_rc_dst");
    }

    // Duration available in core since Rust 1.25:
    // https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations
    if minor >= 25 {
        println!("cargo:rustc-cfg=core_duration");
    }

    // 128-bit integers stabilized in Rust 1.26:
    // https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
    //
    // Disabled on Emscripten targets as Emscripten doesn't
    // currently support integers larger than 64 bits.
    if minor >= 26 && !emscripten {
        println!("cargo:rustc-cfg=integer128");
    }

    // Inclusive ranges methods stabilized in Rust 1.27:
    // https://github.com/rust-lang/rust/pull/50758
    if minor >= 27 {
        println!("cargo:rustc-cfg=range_inclusive");
    }

    // Non-zero integers stabilized in Rust 1.28:
    // https://github.com/rust-lang/rust/pull/50808
    if minor >= 28 {
        println!("cargo:rustc-cfg=num_nonzero");
    }

    if minor >= 34 && has_atomic_integers {
        println!("cargo:rustc-cfg=std_integer_atomics");
    }
}

fn rustc_minor_version() -> Option<u32> {
    let rustc = match env::var_os("RUSTC") {
        Some(rustc) => rustc,
        None => return None,
    };

    let output = match Command::new(rustc).arg("--version").output() {
        Ok(output) => output,
        Err(_) => return None,
    };

    let version = match str::from_utf8(&output.stdout) {
        Ok(version) => version,
        Err(_) => return None,
    };

    let mut pieces = version.split('.');
    if pieces.next() != Some("rustc 1") {
        return None;
    }

    let next = match pieces.next() {
        Some(next) => next,
        None => return None,
    };

    u32::from_str(next).ok()
}

fn target_has_at_least_atomic_u64(target: &str) -> bool {
    // The cfg variable target_has_atomic is unstable
    // so this data comes from the  src/librustc_target/spec/*.rs
    // files in the rust source. Generally, it's 64-bit platforms
    // plus i686.
    if target.starts_with("x86_64") || target.starts_with("i686") ||
        target.starts_with("aarch64") || target.starts_with("powerpc64") ||
        target.starts_with("sparc64") || target.starts_with("mips64el") {
        true
    } else {
        false
    }
}
<|endoftext|>


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

#![allow(non_snake_case)]

extern crate test;
use self::test::Bencher;
use std::collections::HashSet;
use unify::{UnifyKey, UnificationTable};

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct UnitKey(u32);

impl UnifyKey for UnitKey {
    type Value = ();
    fn index(&self) -> u32 { self.0 }
    fn from_index(u: u32) -> UnitKey { UnitKey(u) }
    fn tag(_: Option<UnitKey>) -> &'static str { "UnitKey" }
}

#[test]
fn basic() {
    let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
    let k1 = ut.new_key(());
    let k2 = ut.new_key(());
    assert_eq!(ut.unioned(k1, k2), false);
    ut.union(k1, k2);
    assert_eq!(ut.unioned(k1, k2), true);
}

#[test]
fn big_array() {
    let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
    let mut keys = Vec::new();
    const MAX: usize = 1 << 15;

    for _ in 0..MAX {
        keys.push(ut.new_key(()));
    }

    for i in 1..MAX {
        let l = keys[i-1];
        let r = keys[i];
        ut.union(l, r);
    }

    for i in 0..MAX {
        assert!(ut.unioned(keys[0], keys[i]));
    }
}

#[bench]
fn big_array_bench(b: &mut Bencher) {
    let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
    let mut keys = Vec::new();
    const MAX: usize = 1 << 15;

    for _ in 0..MAX {
        keys.push(ut.new_key(()));
    }

    b.iter(|| {
        for i in 1..MAX {
            let l = keys[i-1];
            let r = keys[i];
            ut.union(l, r);
        }

        for i in 0..MAX {
            assert!(ut.unioned(keys[0], keys[i]));
        }
    })
}

#[test]
fn even_odd() {
    let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
    let mut keys = Vec::new();
    const MAX: usize = 1 << 10;

    for i in 0..MAX {
        let key = ut.new_key(());
        keys.push(key);

        if i >= 2 {
            ut.union(key, keys[i-2]);
        }
    }

    for i in 1..MAX {
        assert!(!ut.unioned(keys[i-1], keys[i]));
    }

    for i in 2..MAX {
        assert!(ut.unioned(keys[i-2], keys[i]));
    }
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct IntKey(u32);

impl UnifyKey for IntKey {
    type Value = Option<i32>;
    fn index(&self) -> u32 { self.0 }
    fn from_index(u: u32) -> IntKey { IntKey(u) }
    fn tag(_: Option<IntKey>) -> &'static str { "IntKey" }
}

/// Test unifying a key whose value is `Some(_)`  with a key whose value is `None`.
/// Afterwards both should be `Some(_)`.
#[test]
fn unify_key_Some_key_None() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    let k2 = ut.new_key(None);
    assert!(ut.unify_var_var(k1, k2).is_ok());
    assert_eq!(ut.probe(k2), Some(22));
    assert_eq!(ut.probe(k1), Some(22));
}

/// Test unifying a key whose value is `None`  with a key whose value is `Some(_)`.
/// Afterwards both should be `Some(_)`.
#[test]
fn unify_key_None_key_Some() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    let k2 = ut.new_key(None);
    assert!(ut.unify_var_var(k2, k1).is_ok());
    assert_eq!(ut.probe(k2), Some(22));
    assert_eq!(ut.probe(k1), Some(22));
}

/// Test unifying a key whose value is `Some(x)` with a key whose value is `Some(y)`.
/// This should yield an error.
#[test]
fn unify_key_Some_x_key_Some_y() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    let k2 = ut.new_key(Some(23));
    assert_eq!(ut.unify_var_var(k1, k2), Err((22, 23)));
    assert_eq!(ut.unify_var_var(k2, k1), Err((23, 22)));
    assert_eq!(ut.probe(k1), Some(22));
    assert_eq!(ut.probe(k2), Some(23));
}

/// Test unifying a key whose value is `Some(x)` with a key whose value is `Some(x)`.
/// This should be ok.
#[test]
fn unify_key_Some_x_key_Some_x() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    let k2 = ut.new_key(Some(22));
    assert!(ut.unify_var_var(k1, k2).is_ok());
    assert_eq!(ut.probe(k1), Some(22));
    assert_eq!(ut.probe(k2), Some(22));
}

/// Test unifying a key whose value is `None` with a value is `x`.
/// Afterwards key should be `x`.
#[test]
fn unify_key_None_val() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(None);
    assert!(ut.unify_var_value(k1, 22).is_ok());
    assert_eq!(ut.probe(k1), Some(22));
}

/// Test unifying a key whose value is `Some(x)` with the value `y`.
/// This should yield an error.
#[test]
fn unify_key_Some_x_val_y() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    assert_eq!(ut.unify_var_value(k1, 23), Err((22, 23)));
    assert_eq!(ut.probe(k1), Some(22));
}

/// Test unifying a key whose value is `Some(x)` with the value `x`.
/// This should be ok.
#[test]
fn unify_key_Some_x_val_x() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    assert!(ut.unify_var_value(k1, 22).is_ok());
    assert_eq!(ut.probe(k1), Some(22));
}

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

#![allow(non_snake_case)]

extern crate test;
use self::test::Bencher;
use unify::{UnifyKey, UnificationTable};

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct UnitKey(u32);

impl UnifyKey for UnitKey {
    type Value = ();
    fn index(&self) -> u32 { self.0 }
    fn from_index(u: u32) -> UnitKey { UnitKey(u) }
    fn tag(_: Option<UnitKey>) -> &'static str { "UnitKey" }
}

#[test]
fn basic() {
    let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
    let k1 = ut.new_key(());
    let k2 = ut.new_key(());
    assert_eq!(ut.unioned(k1, k2), false);
    ut.union(k1, k2);
    assert_eq!(ut.unioned(k1, k2), true);
}

#[test]
fn big_array() {
    let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
    let mut keys = Vec::new();
    const MAX: usize = 1 << 15;

    for _ in 0..MAX {
        keys.push(ut.new_key(()));
    }

    for i in 1..MAX {
        let l = keys[i-1];
        let r = keys[i];
        ut.union(l, r);
    }

    for i in 0..MAX {
        assert!(ut.unioned(keys[0], keys[i]));
    }
}

#[bench]
fn big_array_bench(b: &mut Bencher) {
    let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
    let mut keys = Vec::new();
    const MAX: usize = 1 << 15;

    for _ in 0..MAX {
        keys.push(ut.new_key(()));
    }

    b.iter(|| {
        for i in 1..MAX {
            let l = keys[i-1];
            let r = keys[i];
            ut.union(l, r);
        }

        for i in 0..MAX {
            assert!(ut.unioned(keys[0], keys[i]));
        }
    })
}

#[test]
fn even_odd() {
    let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
    let mut keys = Vec::new();
    const MAX: usize = 1 << 10;

    for i in 0..MAX {
        let key = ut.new_key(());
        keys.push(key);

        if i >= 2 {
            ut.union(key, keys[i-2]);
        }
    }

    for i in 1..MAX {
        assert!(!ut.unioned(keys[i-1], keys[i]));
    }

    for i in 2..MAX {
        assert!(ut.unioned(keys[i-2], keys[i]));
    }
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct IntKey(u32);

impl UnifyKey for IntKey {
    type Value = Option<i32>;
    fn index(&self) -> u32 { self.0 }
    fn from_index(u: u32) -> IntKey { IntKey(u) }
    fn tag(_: Option<IntKey>) -> &'static str { "IntKey" }
}

/// Test unifying a key whose value is `Some(_)`  with a key whose value is `None`.
/// Afterwards both should be `Some(_)`.
#[test]
fn unify_key_Some_key_None() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    let k2 = ut.new_key(None);
    assert!(ut.unify_var_var(k1, k2).is_ok());
    assert_eq!(ut.probe(k2), Some(22));
    assert_eq!(ut.probe(k1), Some(22));
}

/// Test unifying a key whose value is `None`  with a key whose value is `Some(_)`.
/// Afterwards both should be `Some(_)`.
#[test]
fn unify_key_None_key_Some() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    let k2 = ut.new_key(None);
    assert!(ut.unify_var_var(k2, k1).is_ok());
    assert_eq!(ut.probe(k2), Some(22));
    assert_eq!(ut.probe(k1), Some(22));
}

/// Test unifying a key whose value is `Some(x)` with a key whose value is `Some(y)`.
/// This should yield an error.
#[test]
fn unify_key_Some_x_key_Some_y() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    let k2 = ut.new_key(Some(23));
    assert_eq!(ut.unify_var_var(k1, k2), Err((22, 23)));
    assert_eq!(ut.unify_var_var(k2, k1), Err((23, 22)));
    assert_eq!(ut.probe(k1), Some(22));
    assert_eq!(ut.probe(k2), Some(23));
}

/// Test unifying a key whose value is `Some(x)` with a key whose value is `Some(x)`.
/// This should be ok.
#[test]
fn unify_key_Some_x_key_Some_x() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    let k2 = ut.new_key(Some(22));
    assert!(ut.unify_var_var(k1, k2).is_ok());
    assert_eq!(ut.probe(k1), Some(22));
    assert_eq!(ut.probe(k2), Some(22));
}

/// Test unifying a key whose value is `None` with a value is `x`.
/// Afterwards key should be `x`.
#[test]
fn unify_key_None_val() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(None);
    assert!(ut.unify_var_value(k1, 22).is_ok());
    assert_eq!(ut.probe(k1), Some(22));
}

/// Test unifying a key whose value is `Some(x)` with the value `y`.
/// This should yield an error.
#[test]
fn unify_key_Some_x_val_y() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    assert_eq!(ut.unify_var_value(k1, 23), Err((22, 23)));
    assert_eq!(ut.probe(k1), Some(22));
}

/// Test unifying a key whose value is `Some(x)` with the value `x`.
/// This should be ok.
#[test]
fn unify_key_Some_x_val_x() {
    let mut ut: UnificationTable<IntKey> = UnificationTable::new();
    let k1 = ut.new_key(Some(22));
    assert!(ut.unify_var_value(k1, 22).is_ok());
    assert_eq!(ut.probe(k1), Some(22));
}

<|endoftext|>