<commit_before>/*
    Copyright 2017 Andrew Medworth <github@medworth.org.uk>

    This file is part of Dots-and-Boxes Engine.

    Dots-and-Boxes Engine is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Dots-and-Boxes Engine 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Dots-and-Boxes Engine.  If not, see <http://www.gnu.org/licenses/>.
*/
use game::{Move, Position, Side};
use nimstring;
use std::collections::HashMap;
use std::isize;

// Evaluate a position given a set of moves to consider
fn eval_moves(pos: &mut Position, moves: &Vec<Move>,
              cache: &mut HashMap<usize, (isize, Move)>) -> (isize, Option<Move>) {
    if moves.is_empty() {
        return (0, None);
    }
    let mut value = isize::MIN;
    let mut best_move = moves[0];
    for &m in moves {
        let outcome = pos.make_move(m.x, m.y, m.side);
        let sign = if outcome.coins_captured > 0 { 1 } else { -1 };
        let (next_val, _) = eval_cache(pos, cache);
        let sub_val = (outcome.coins_captured as isize) + sign * next_val;
        pos.undo_move(m.x, m.y, m.side);
        if sub_val > value {
            value = sub_val;
            best_move = m;
        }
    }
    cache.insert(pos.zhash(), (value, best_move));
    (value, Some(best_move))
}

// Given a loony position and the capture, find the corresponding double-dealing move
fn find_ddeal_move(pos: &Position, capture: Move) -> Move {
    // (capture.x, capture.y) might be the valency-1 coin or the valency-2 one
    let (v2_x, v2_y, excl_side) = if pos.valency(capture.x, capture.y) == 1 {
        let (x, y) = pos.offset(capture.x, capture.y, capture.side).unwrap();
        (x, y, capture.side.opposite())
    } else {
        (capture.x, capture.y, capture.side)
    };

    if pos.valency(v2_x, v2_y) != 2 {
        panic!("Expected ({},{}) to have valency 2, found {} in {}",
               v2_x, v2_y, pos.valency(v2_x, v2_y), pos);
    }

    for s in Side::all_except(excl_side) {
        if pos.is_legal_move(v2_x, v2_y, s) {
            return Move{x: v2_x, y: v2_y, side: s};
        }
    }

    panic!("Could not find double-dealing move corresponding to {} in {}", capture, pos);
}

// Determine what moves deserve consideration in a given position
fn moves_to_consider(pos: &mut Position) -> Vec<Move> {
    let legal_moves = pos.legal_moves();

    // If there are any captures which don't affect looniness, just go ahead and make those
    let is_loony = nimstring::is_loony(pos);
    let mut capture: Option<Move> = None;
    for &m in &legal_moves {
        let captures = pos.would_capture(m.x, m.y, m.side);
        if captures == 0 {
            continue;
        }
        capture = Some(m);
        if !is_loony || nimstring::would_be_loony(pos, m.x, m.y, m.side) {
            return vec!(m);
        }
    }

    // Consider only capturing all and double-dealing in the loony case
    // TODO: Use other canonical play results to further reduce the set of moves considered
    if is_loony {
        let capture = capture.unwrap();
        let ddeal_move = find_ddeal_move(pos, capture);
        vec!(capture, ddeal_move)
    } else {
        legal_moves
    }
}

fn eval_cache(pos: &mut Position, cache: &mut HashMap<usize, (isize, Move)>) -> (isize, Option<Move>) {
    // TODO: Use alpha-beta pruning
    if let Some(&(val, best_move)) = cache.get(&pos.zhash()) {
        return (val, Some(best_move));
    }

    let moves = moves_to_consider(pos);
    eval_moves(pos, &moves, cache)
}

// Calculate the value function of a given position and a move which achieves that value
pub fn eval(pos: &Position) -> (isize, Option<Move>) {
    let mut cache = HashMap::new();
    let mut pos = pos.clone();
    eval_cache(&mut pos, &mut cache)
}

#[cfg(test)]
mod test {
    use eval::*;
    use examples::*;

    #[test]
    fn eval_chain() {
        for i in 1..10 {
            let mut chain = make_chain(i);
            let (val, _) = eval(&mut chain);
            assert_eq!(-(i as isize), val);
        }
    }

    #[test]
    fn eval_double_chain() {
        let (val, _) = eval(&mut double_chain(1));
        assert_eq!(0, val);
        for i in 2..10 {
            let mut pos = double_chain(i);
            let (val, _) = eval(&mut pos);
            assert_eq!(4 - 2*(i as isize), val, "Evaluation of double chain length {}", i);
        }
    }

    #[test]
    fn eval_multi_chains() {
        let mut pos = multi_chains(3, 4);

        let (val, _) = eval(&mut pos);
        assert_eq!(-2, val);
        pos.make_move(0, 0, Side::Left);

        let (val, best_move) = eval(&mut pos);
        assert_eq!(2, val);
        assert!(pos.moves_equivalent(best_move.unwrap(), Move{x: 0, y: 0, side: Side::Right}));
        pos.make_move(0, 0, Side::Right);

        let (val, best_move) = eval(&mut pos);
        assert_eq!(1, val);
        assert!(pos.moves_equivalent(best_move.unwrap(), Move{x: 1, y: 0, side: Side::Right}));
        pos.make_move(1, 0, Side::Right);

        let (val, best_move) = eval(&mut pos);
        assert_eq!(0, val);
        assert!(pos.moves_equivalent(best_move.unwrap(), Move{x: 2, y: 0, side: Side::Right}));
        pos.make_move(2, 0, Side::Right);

        let (val, _) = eval(&mut pos);
        assert_eq!(-1, val);
    }

    #[test]
    fn eval_double_loop() {
        for i in 2..8 {
            let mut pos = double_loop(i);
            let (val, _) = eval(&mut pos);
            assert_eq!(8 - 4*(i as isize), val, "Evaluation of double loop width {}", i);
        }
    }

    #[test]
    fn eval_open_chain() {
        for i in 2..8 {
            let mut pos = make_chain(i);
            pos.make_move(0, 0, Side::Left);
            let (val, best_move) = eval(&mut pos);
            assert_eq!(i as isize, val, "Evaluation of open {}-chain", i);
            let best_move = best_move.unwrap();
            assert!(pos.moves_equivalent(best_move, Move{x: 0, y: 0, side: Side::Right}));
        }
    }

    #[test]
    fn eval_ex3p1() {
        let mut pos = ex3p1();
        let (val, best_move) = eval(&mut pos);
        let best_move = best_move.unwrap();
        assert_eq!(3, val);
        assert!(pos.moves_equivalent(best_move, Move{x: 2, y: 1, side: Side::Bottom}));

        pos.make_move(2, 1, Side::Bottom);
        let (val, best_move) = eval(&mut pos);
        let best_move = best_move.unwrap();
        assert_eq!(-3, val);
        assert!(pos.moves_equivalent(best_move, Move{x: 0, y: 0, side: Side::Bottom}));

        pos.make_move(0, 0, Side::Bottom);
        let (val, _) = eval(&mut pos);
        assert_eq!(3, val);

        pos.undo_move(0, 0, Side::Bottom);
        pos.make_move(0, 2, Side::Left);
        let (val, _) = eval(&mut pos);
        assert_eq!(5, val);
    }
}
<commit_msg>Remove TODO: alpha-beta pruning stays on branch alphabeta for now<commit_after>/*
    Copyright 2017 Andrew Medworth <github@medworth.org.uk>

    This file is part of Dots-and-Boxes Engine.

    Dots-and-Boxes Engine is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Dots-and-Boxes Engine 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Dots-and-Boxes Engine.  If not, see <http://www.gnu.org/licenses/>.
*/
use game::{Move, Position, Side};
use nimstring;
use std::collections::HashMap;
use std::isize;

// Evaluate a position given a set of moves to consider
fn eval_moves(pos: &mut Position, moves: &Vec<Move>,
              cache: &mut HashMap<usize, (isize, Move)>) -> (isize, Option<Move>) {
    if moves.is_empty() {
        return (0, None);
    }
    let mut value = isize::MIN;
    let mut best_move = moves[0];
    for &m in moves {
        let outcome = pos.make_move(m.x, m.y, m.side);
        let sign = if outcome.coins_captured > 0 { 1 } else { -1 };
        let (next_val, _) = eval_cache(pos, cache);
        let sub_val = (outcome.coins_captured as isize) + sign * next_val;
        pos.undo_move(m.x, m.y, m.side);
        if sub_val > value {
            value = sub_val;
            best_move = m;
        }
    }
    cache.insert(pos.zhash(), (value, best_move));
    (value, Some(best_move))
}

// Given a loony position and the capture, find the corresponding double-dealing move
fn find_ddeal_move(pos: &Position, capture: Move) -> Move {
    // (capture.x, capture.y) might be the valency-1 coin or the valency-2 one
    let (v2_x, v2_y, excl_side) = if pos.valency(capture.x, capture.y) == 1 {
        let (x, y) = pos.offset(capture.x, capture.y, capture.side).unwrap();
        (x, y, capture.side.opposite())
    } else {
        (capture.x, capture.y, capture.side)
    };

    if pos.valency(v2_x, v2_y) != 2 {
        panic!("Expected ({},{}) to have valency 2, found {} in {}",
               v2_x, v2_y, pos.valency(v2_x, v2_y), pos);
    }

    for s in Side::all_except(excl_side) {
        if pos.is_legal_move(v2_x, v2_y, s) {
            return Move{x: v2_x, y: v2_y, side: s};
        }
    }

    panic!("Could not find double-dealing move corresponding to {} in {}", capture, pos);
}

// Determine what moves deserve consideration in a given position
fn moves_to_consider(pos: &mut Position) -> Vec<Move> {
    let legal_moves = pos.legal_moves();

    // If there are any captures which don't affect looniness, just go ahead and make those
    let is_loony = nimstring::is_loony(pos);
    let mut capture: Option<Move> = None;
    for &m in &legal_moves {
        let captures = pos.would_capture(m.x, m.y, m.side);
        if captures == 0 {
            continue;
        }
        capture = Some(m);
        if !is_loony || nimstring::would_be_loony(pos, m.x, m.y, m.side) {
            return vec!(m);
        }
    }

    // Consider only capturing all and double-dealing in the loony case
    // TODO: Use other canonical play results to further reduce the set of moves considered
    if is_loony {
        let capture = capture.unwrap();
        let ddeal_move = find_ddeal_move(pos, capture);
        vec!(capture, ddeal_move)
    } else {
        legal_moves
    }
}

fn eval_cache(pos: &mut Position, cache: &mut HashMap<usize, (isize, Move)>) -> (isize, Option<Move>) {
    if let Some(&(val, best_move)) = cache.get(&pos.zhash()) {
        return (val, Some(best_move));
    }

    let moves = moves_to_consider(pos);
    eval_moves(pos, &moves, cache)
}

// Calculate the value function of a given position and a move which achieves that value
pub fn eval(pos: &Position) -> (isize, Option<Move>) {
    let mut cache = HashMap::new();
    let mut pos = pos.clone();
    eval_cache(&mut pos, &mut cache)
}

#[cfg(test)]
mod test {
    use eval::*;
    use examples::*;

    #[test]
    fn eval_chain() {
        for i in 1..10 {
            let mut chain = make_chain(i);
            let (val, _) = eval(&mut chain);
            assert_eq!(-(i as isize), val);
        }
    }

    #[test]
    fn eval_double_chain() {
        let (val, _) = eval(&mut double_chain(1));
        assert_eq!(0, val);
        for i in 2..10 {
            let mut pos = double_chain(i);
            let (val, _) = eval(&mut pos);
            assert_eq!(4 - 2*(i as isize), val, "Evaluation of double chain length {}", i);
        }
    }

    #[test]
    fn eval_multi_chains() {
        let mut pos = multi_chains(3, 4);

        let (val, _) = eval(&mut pos);
        assert_eq!(-2, val);
        pos.make_move(0, 0, Side::Left);

        let (val, best_move) = eval(&mut pos);
        assert_eq!(2, val);
        assert!(pos.moves_equivalent(best_move.unwrap(), Move{x: 0, y: 0, side: Side::Right}));
        pos.make_move(0, 0, Side::Right);

        let (val, best_move) = eval(&mut pos);
        assert_eq!(1, val);
        assert!(pos.moves_equivalent(best_move.unwrap(), Move{x: 1, y: 0, side: Side::Right}));
        pos.make_move(1, 0, Side::Right);

        let (val, best_move) = eval(&mut pos);
        assert_eq!(0, val);
        assert!(pos.moves_equivalent(best_move.unwrap(), Move{x: 2, y: 0, side: Side::Right}));
        pos.make_move(2, 0, Side::Right);

        let (val, _) = eval(&mut pos);
        assert_eq!(-1, val);
    }

    #[test]
    fn eval_double_loop() {
        for i in 2..8 {
            let mut pos = double_loop(i);
            let (val, _) = eval(&mut pos);
            assert_eq!(8 - 4*(i as isize), val, "Evaluation of double loop width {}", i);
        }
    }

    #[test]
    fn eval_open_chain() {
        for i in 2..8 {
            let mut pos = make_chain(i);
            pos.make_move(0, 0, Side::Left);
            let (val, best_move) = eval(&mut pos);
            assert_eq!(i as isize, val, "Evaluation of open {}-chain", i);
            let best_move = best_move.unwrap();
            assert!(pos.moves_equivalent(best_move, Move{x: 0, y: 0, side: Side::Right}));
        }
    }

    #[test]
    fn eval_ex3p1() {
        let mut pos = ex3p1();
        let (val, best_move) = eval(&mut pos);
        let best_move = best_move.unwrap();
        assert_eq!(3, val);
        assert!(pos.moves_equivalent(best_move, Move{x: 2, y: 1, side: Side::Bottom}));

        pos.make_move(2, 1, Side::Bottom);
        let (val, best_move) = eval(&mut pos);
        let best_move = best_move.unwrap();
        assert_eq!(-3, val);
        assert!(pos.moves_equivalent(best_move, Move{x: 0, y: 0, side: Side::Bottom}));

        pos.make_move(0, 0, Side::Bottom);
        let (val, _) = eval(&mut pos);
        assert_eq!(3, val);

        pos.undo_move(0, 0, Side::Bottom);
        pos.make_move(0, 2, Side::Left);
        let (val, _) = eval(&mut pos);
        assert_eq!(5, val);
    }
}
<|endoftext|>


<commit_before>// 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/.

extern crate egg_mode;

mod common;

use common::tokio_core::reactor;

fn main() {
    let con_key = include_str!("common/consumer_key").trim();
    let con_secret = include_str!("common/consumer_secret").trim();

    let con_token = egg_mode::KeyPair::new(con_key, con_secret);

    let mut core = reactor::Core::new().unwrap();
    let handle = core.handle();

    println!("Pulling up the bearer token...");
    let token = core.run(egg_mode::bearer_token(&con_token, &handle)).unwrap();

    println!("Pulling up a user timeline...");
    let mut timeline = egg_mode::tweet::user_timeline("rustlang", false, true, &token, &handle).with_page_size(5);

    for tweet in core.run(timeline.start()).unwrap() {
        println!("");
        common::print_tweet(&tweet);
    }
}
<commit_msg>fix examples/bearer.rs<commit_after>// 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/.

extern crate egg_mode;

mod common;

use common::tokio_core::reactor;

fn main() {
    let con_key = include_str!("common/consumer_key").trim();
    let con_secret = include_str!("common/consumer_secret").trim();

    let con_token = egg_mode::KeyPair::new(con_key, con_secret);

    let mut core = reactor::Core::new().unwrap();
    let handle = core.handle();

    println!("Pulling up the bearer token...");
    let token = core.run(egg_mode::bearer_token(&con_token, &handle)).unwrap();

    println!("Pulling up a user timeline...");
    let timeline = egg_mode::tweet::user_timeline("rustlang", false, true, &token, &handle).with_page_size(5);

    let (_timeline, feed) = core.run(timeline.start()).unwrap();
    for tweet in feed {
        println!("");
        common::print_tweet(&tweet);
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

#![warn(clippy::for_kv_map)]
#![allow(clippy::used_underscore_binding)]

use std::collections::*;
use std::rc::Rc;

fn main() {
    let m: HashMap<u64, u64> = HashMap::new();
    for (_, v) in &m {
        let _v = v;
    }

    let m: Rc<HashMap<u64, u64>> = Rc::new(HashMap::new());
    for (_, v) in &*m {
        let _v = v;
        // Here the `*` is not actually necessary, but the test tests that we don't
        // suggest
        // `in *m.values()` as we used to
    }

    let mut m: HashMap<u64, u64> = HashMap::new();
    for (_, v) in &mut m {
        let _v = v;
    }

    let m: &mut HashMap<u64, u64> = &mut HashMap::new();
    for (_, v) in &mut *m {
        let _v = v;
    }

    let m: HashMap<u64, u64> = HashMap::new();
    let rm = &m;
    for (k, _value) in rm {
        let _k = k;
    }
    test_for_kv_map();
}

fn test_for_kv_map() {
    let m: HashMap<u64, u64> = HashMap::new();

    // No error, _value is actually used
    for (k, _value) in &m {
        let _ = _value;
        let _k = k;
    }
}
<commit_msg>Auto merge of #3622 - m-cat:master, r=phansch<commit_after>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

#![warn(clippy::for_kv_map)]
#![allow(clippy::used_underscore_binding)]

use std::collections::*;
use std::rc::Rc;

fn main() {
    let m: HashMap<u64, u64> = HashMap::new();
    for (_, v) in &m {
        let _v = v;
    }

    let m: Rc<HashMap<u64, u64>> = Rc::new(HashMap::new());
    for (_, v) in &*m {
        let _v = v;
        // Here the `*` is not actually necessary, but the test tests that we don't
        // suggest
        // `in *m.values()` as we used to
    }

    let mut m: HashMap<u64, u64> = HashMap::new();
    for (_, v) in &mut m {
        let _v = v;
    }

    let m: &mut HashMap<u64, u64> = &mut HashMap::new();
    for (_, v) in &mut *m {
        let _v = v;
    }

    let m: HashMap<u64, u64> = HashMap::new();
    let rm = &m;
    for (k, _value) in rm {
        let _k = k;
    }

    // The following should not produce warnings.

    let m: HashMap<u64, u64> = HashMap::new();
    // No error, _value is actually used
    for (k, _value) in &m {
        let _ = _value;
        let _k = k;
    }

    let m: HashMap<u64, String> = Default::default();
    for (_, v) in m {
        let _v = v;
    }
}
<|endoftext|>


<commit_before>extern crate gl;
extern crate glutin;
extern crate openvr;

use std::os::raw::c_void;
use std::ptr;
use openvr::ffi;

fn main() {
    unsafe {
        let window =
                glutin::WindowBuilder::new()
                .with_title("OpenVR Example".to_string())
                .with_gl_profile(glutin::GlProfile::Core)
                .with_dimensions(800, 600)
                .build()
                .expect("create window");

        window.make_current().expect("make current");

        gl::load_with(|symbol| window.get_proc_address(symbol) as *mut c_void);

        // init OpenVR ----------------------------------------------------------------------------
        let mut context = openvr::initialize().expect("OpenVR init");

        let (tex_width, tex_height) = context.system.get_recommended_render_target_size();

        'main_loop: loop {
            // get poses --------------------------------------------------------------------------
            let _ = context.compositor.wait_get_poses();

            // submit each eye --------------------------------------------------------------------
            for eye in &[ffi::EVREye::Eye_Left, ffi::EVREye::Eye_Right] {
                // "render" the sceen for each eye
                let pixel =
                    if *eye == ffi::EVREye::Eye_Left {
                        0xff0000ffu32
                    } else {
                        0xff00ff00u32
                    };

                let texture_data = vec![pixel; (tex_width * tex_height) as usize];

                let mut texture = 0;

                gl::GenTextures(1, &mut texture);
                gl::BindTexture(gl::TEXTURE_2D, texture);

                gl::TexImage2D(
                    gl::TEXTURE_2D,
                    0,
                    gl::RGBA8 as i32,
                    tex_width as i32,
                    tex_height as i32,
                    0,
                    gl::RGBA,
                    gl::UNSIGNED_BYTE,
                    texture_data.as_ptr() as *const _
                );

                let mut desc = ffi::Texture {
                    handle:         texture as *mut ::std::os::raw::c_void,
                    eType:          ffi::EGraphicsAPIConvention::API_OpenGL,
                    eColorSpace:    ffi::EColorSpace::Gamma
                };

                // submit to the compositor
                let error = context.compositor.submit(
                    *eye,
                    &mut desc,
                    ptr::null::<ffi::VRTextureBounds>() as *mut _,
                    ffi::EVRSubmitFlags::Submit_Default
                );

                if error != ffi::EVRCompositorError::None {
                    println!("[openvr] compositor error: {:?}", error);
                }

                gl::DeleteTextures(1, &mut texture);
            }

            // process window events --------------------------------------------------------------
            for event in window.poll_events() {
                match event {
                    glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::Escape))
                    | glutin::Event::Closed => break 'main_loop,
                    _ => {}
                }
            }

            match window.swap_buffers() {
                Ok(()) => (),
                Err(_) => panic!("Failed to swap buffers")
            }
        }
    }
}
<commit_msg>fix example on nvidia<commit_after>extern crate gl;
extern crate glutin;
extern crate openvr;

use std::os::raw::c_void;
use openvr::ffi;

fn main() {
    unsafe {
        let window =
                glutin::WindowBuilder::new()
                .with_title("OpenVR Example".to_string())
                .with_gl_profile(glutin::GlProfile::Core)
                .with_dimensions(800, 600)
                .build()
                .expect("create window");

        window.make_current().expect("make current");

        gl::load_with(|symbol| window.get_proc_address(symbol) as *mut c_void);

        // init OpenVR ----------------------------------------------------------------------------
        let mut context = openvr::initialize().expect("OpenVR init");

        let (tex_width, tex_height) = context.system.get_recommended_render_target_size();

        let mut textures = [0; 2];
        gl::GenTextures(2, textures.as_mut_ptr());

        for i in 0..2 {
            gl::BindTexture(gl::TEXTURE_2D, textures[i]);

            // Not generating mips
            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAX_LEVEL, 0);

            let pixel =
                if i == 0 {
                    0xff0000ffu32
                } else {
                    0xff00ff00u32
                };

            let texture_data = vec![pixel; (tex_width * tex_height) as usize];

            gl::TexImage2D(
                gl::TEXTURE_2D,
                0,
                gl::RGBA8 as i32,
                tex_width as i32,
                tex_height as i32,
                0,
                gl::RGBA,
                gl::UNSIGNED_BYTE,
                texture_data.as_ptr() as *const _
            );
        }

        'main_loop: loop {
            // get poses --------------------------------------------------------------------------
            let _poses = context.compositor.wait_get_poses();

            // submit each eye --------------------------------------------------------------------
            for eye in &[ffi::EVREye::Eye_Left, ffi::EVREye::Eye_Right] {
                let eye_index = *eye as usize;

                // "render" the scene for each eye

                let mut desc = ffi::Texture {
                    handle:         textures[eye_index] as *mut ::std::os::raw::c_void,
                    eType:          ffi::EGraphicsAPIConvention::API_OpenGL,
                    eColorSpace:    ffi::EColorSpace::Gamma
                };

                // submit to the compositor
                let error = context.compositor.submit(
                    *eye,
                    &mut desc,
                    &mut ffi::VRTextureBounds {
                        uMin:   0.0,
                        vMin:   0.0,
                        uMax:   1.0,
                        vMax:   1.0,
                    },
                    ffi::EVRSubmitFlags::Submit_Default
                );

                if error != ffi::EVRCompositorError::None {
                    println!("[openvr] compositor error: {:?}", error);
                }
            }

            // process window events --------------------------------------------------------------
            for event in window.poll_events() {
                match event {
                    glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::Escape))
                    | glutin::Event::Closed => break 'main_loop,
                    _ => {}
                }
            }

            match window.swap_buffers() {
                Ok(()) => (),
                Err(_) => panic!("Failed to swap buffers")
            }
        }
    }
}
<|endoftext|>


<commit_before>// (c) 2015-2016 Productize SPRL <joost@productize.be>

extern crate symbolic_expressions;

fn main() {
    let s = symbolic_expressions::parser::parse_file("examples/SILABS_EFM32_QFN24.kicad_mod")
        .unwrap();
    println!("{}", s);
}
<commit_msg>cargo fmt<commit_after>// (c) 2015-2016 Productize SPRL <joost@productize.be>

extern crate symbolic_expressions;

fn main() {
    let s =
        symbolic_expressions::parser::parse_file("examples/SILABS_EFM32_QFN24.kicad_mod").unwrap();
    println!("{}", s);
}
<|endoftext|>


<commit_before>use crate::common::util::*;

// FIXME: this depends on the system having true and false in PATH
//        the best solution is probably to generate some test binaries that we can call for any
//        utility that requires executing another program (kill, for instance)
#[test]
fn test_subcommand_return_code() {
    new_ucmd!().arg("1").arg("true").succeeds();

    new_ucmd!().arg("1").arg("false").run().status_code(1);
}

#[test]
fn test_command_with_args() {
    new_ucmd!()
        .args(&["1700", "echo", "-n", "abcd"])
        .succeeds()
        .stdout_only("abcd");
}

#[test]
fn test_verbose() {
    for &verbose_flag in &["-v", "--verbose"] {
        new_ucmd!()
            .args(&[verbose_flag, ".1", "sleep", "10"])
            .fails()
            .stderr_only("timeout: sending signal TERM to command 'sleep'");
        new_ucmd!()
            .args(&[verbose_flag, "-s0", "-k.1", ".1", "sleep", "10"])
            .fails()
            .stderr_only("timeout: sending signal EXIT to command 'sleep'\ntimeout: sending signal KILL to command 'sleep'");
    }
}

#[test]
fn test_zero_timeout() {
    new_ucmd!()
        .args(&["-v", "0", "sleep", ".1"])
        .succeeds()
        .no_stderr()
        .no_stdout();
    new_ucmd!()
        .args(&["-v", "0", "-s0", "-k0", "sleep", ".1"])
        .succeeds()
        .no_stderr()
        .no_stdout();
}
<commit_msg>timeout: add a test for empty arg<commit_after>use crate::common::util::*;

// FIXME: this depends on the system having true and false in PATH
//        the best solution is probably to generate some test binaries that we can call for any
//        utility that requires executing another program (kill, for instance)
#[test]
fn test_subcommand_return_code() {
    new_ucmd!().arg("1").arg("true").succeeds();

    new_ucmd!().arg("1").arg("false").run().status_code(1);
}

#[test]
fn test_command_with_args() {
    new_ucmd!()
        .args(&["1700", "echo", "-n", "abcd"])
        .succeeds()
        .stdout_only("abcd");
}

#[test]
fn test_verbose() {
    for &verbose_flag in &["-v", "--verbose"] {
        new_ucmd!()
            .args(&[verbose_flag, ".1", "sleep", "10"])
            .fails()
            .stderr_only("timeout: sending signal TERM to command 'sleep'");
        new_ucmd!()
            .args(&[verbose_flag, "-s0", "-k.1", ".1", "sleep", "10"])
            .fails()
            .stderr_only("timeout: sending signal EXIT to command 'sleep'\ntimeout: sending signal KILL to command 'sleep'");
    }
}

#[test]
fn test_zero_timeout() {
    new_ucmd!()
        .args(&["-v", "0", "sleep", ".1"])
        .succeeds()
        .no_stderr()
        .no_stdout();
    new_ucmd!()
        .args(&["-v", "0", "-s0", "-k0", "sleep", ".1"])
        .succeeds()
        .no_stderr()
        .no_stdout();
}

#[test]
fn test_command_empty_args() {
    new_ucmd!()
        .args(&["", ""])
        .fails()
        .stderr_contains("timeout: empty string");
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

use hir::{AsAssocItem, HirDisplay, Semantics};
use itertools::Itertools;
use ra_ide_db::RootDatabase;
use ra_syntax::{
    ast::{self, AstNode, AttrsOwner, ModuleItemOwner, NameOwner},
    match_ast, SyntaxNode, TextRange,
};

use crate::FileId;
use ast::DocCommentsOwner;
use std::fmt::Display;

#[derive(Debug)]
pub struct Runnable {
    pub range: TextRange,
    pub kind: RunnableKind,
}

#[derive(Debug)]
pub enum TestId {
    Name(String),
    Path(String),
}

impl Display for TestId {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            TestId::Name(name) => write!(f, "{}", name),
            TestId::Path(path) => write!(f, "{}", path),
        }
    }
}

#[derive(Debug)]
pub enum RunnableKind {
    Test { test_id: TestId, attr: TestAttr },
    TestMod { path: String },
    Bench { test_id: TestId },
    DocTest { test_id: TestId },
    Bin,
}

pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
    let sema = Semantics::new(db);
    let source_file = sema.parse(file_id);
    source_file.syntax().descendants().filter_map(|i| runnable(&sema, i)).collect()
}

fn runnable(sema: &Semantics<RootDatabase>, item: SyntaxNode) -> Option<Runnable> {
    match_ast! {
        match item {
            ast::FnDef(it) => runnable_fn(sema, it),
            ast::Module(it) => runnable_mod(sema, it),
            _ => None,
        }
    }
}

fn runnable_fn(sema: &Semantics<RootDatabase>, fn_def: ast::FnDef) -> Option<Runnable> {
    let name_string = fn_def.name()?.text().to_string();

    let kind = if name_string == "main" {
        RunnableKind::Bin
    } else {
        let test_id = if let Some(module) = sema.to_def(&fn_def).map(|def| def.module(sema.db)) {
            let def = sema.to_def(&fn_def)?;
            let impl_trait_name =
                def.as_assoc_item(sema.db).and_then(|assoc_item| {
                    match assoc_item.container(sema.db) {
                        hir::AssocItemContainer::Trait(trait_item) => {
                            Some(trait_item.name(sema.db).to_string())
                        }
                        hir::AssocItemContainer::ImplDef(impl_def) => impl_def
                            .target_ty(sema.db)
                            .as_adt()
                            .map(|adt| adt.name(sema.db).to_string()),
                    }
                });

            let path_iter = module
                .path_to_root(sema.db)
                .into_iter()
                .rev()
                .filter_map(|it| it.name(sema.db))
                .map(|name| name.to_string());

            let path = if let Some(impl_trait_name) = impl_trait_name {
                path_iter
                    .chain(std::iter::once(impl_trait_name))
                    .chain(std::iter::once(name_string))
                    .join("::")
            } else {
                path_iter.chain(std::iter::once(name_string)).join("::")
            };

            TestId::Path(path)
        } else {
            TestId::Name(name_string)
        };

        if has_test_related_attribute(&fn_def) {
            let attr = TestAttr::from_fn(&fn_def);
            RunnableKind::Test { test_id, attr }
        } else if fn_def.has_atom_attr("bench") {
            RunnableKind::Bench { test_id }
        } else if has_doc_test(&fn_def) {
            RunnableKind::DocTest { test_id }
        } else {
            return None;
        }
    };
    Some(Runnable { range: fn_def.syntax().text_range(), kind })
}

#[derive(Debug)]
pub struct TestAttr {
    pub ignore: bool,
}

impl TestAttr {
    fn from_fn(fn_def: &ast::FnDef) -> TestAttr {
        let ignore = fn_def
            .attrs()
            .filter_map(|attr| attr.simple_name())
            .any(|attribute_text| attribute_text == "ignore");
        TestAttr { ignore }
    }
}

/// This is a method with a heuristics to support test methods annotated with custom test annotations, such as
/// `#[test_case(...)]`, `#[tokio::test]` and similar.
/// Also a regular `#[test]` annotation is supported.
///
/// It may produce false positives, for example, `#[wasm_bindgen_test]` requires a different command to run the test,
/// but it's better than not to have the runnables for the tests at all.
fn has_test_related_attribute(fn_def: &ast::FnDef) -> bool {
    fn_def
        .attrs()
        .filter_map(|attr| attr.path())
        .map(|path| path.syntax().to_string().to_lowercase())
        .any(|attribute_text| attribute_text.contains("test"))
}

fn has_doc_test(fn_def: &ast::FnDef) -> bool {
    fn_def.doc_comment_text().map_or(false, |comment| comment.contains("```"))
}

fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> {
    let has_test_function = module
        .item_list()?
        .items()
        .filter_map(|it| match it {
            ast::ModuleItem::FnDef(it) => Some(it),
            _ => None,
        })
        .any(|f| has_test_related_attribute(&f));
    if !has_test_function {
        return None;
    }
    let range = module.syntax().text_range();
    let module = sema.to_def(&module)?;

    let path =
        module.path_to_root(sema.db).into_iter().rev().filter_map(|it| it.name(sema.db)).join("::");
    Some(Runnable { range, kind: RunnableKind::TestMod { path } })
}

#[cfg(test)]
mod tests {
    use insta::assert_debug_snapshot;

    use crate::mock_analysis::analysis_and_position;

    #[test]
    fn test_runnables() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        fn main() {}

        #[test]
        fn test_foo() {}

        #[test]
        #[ignore]
        fn test_foo() {}
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert_debug_snapshot!(&runnables,
        @r###"
        [
            Runnable {
                range: 1..21,
                kind: Bin,
            },
            Runnable {
                range: 22..46,
                kind: Test {
                    test_id: Path(
                        "test_foo",
                    ),
                    attr: TestAttr {
                        ignore: false,
                    },
                },
            },
            Runnable {
                range: 47..81,
                kind: Test {
                    test_id: Path(
                        "test_foo",
                    ),
                    attr: TestAttr {
                        ignore: true,
                    },
                },
            },
        ]
        "###
                );
    }

    #[test]
    fn test_runnables_doc_test() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        fn main() {}

        /// ```
        /// let x = 5;
        /// ```
        fn foo() {}
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert_debug_snapshot!(&runnables,
        @r###"
        [
            Runnable {
                range: 1..21,
                kind: Bin,
            },
            Runnable {
                range: 22..64,
                kind: DocTest {
                    test_id: Path(
                        "foo",
                    ),
                },
            },
        ]
        "###
                );
    }

    #[test]
    fn test_runnables_doc_test_in_impl() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        fn main() {}

        struct Data;
        impl Data {
            /// ```
            /// let x = 5;
            /// ```
            fn foo() {}
        }
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert_debug_snapshot!(&runnables,
        @r###"
        [
            Runnable {
                range: 1..21,
                kind: Bin,
            },
            Runnable {
                range: 52..106,
                kind: DocTest {
                    test_id: Path(
                        "Data::foo",
                    ),
                },
            },
        ]
        "###
                );
    }

    #[test]
    fn test_runnables_module() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        mod test_mod {
            #[test]
            fn test_foo1() {}
        }
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert_debug_snapshot!(&runnables,
        @r###"
        [
            Runnable {
                range: 1..59,
                kind: TestMod {
                    path: "test_mod",
                },
            },
            Runnable {
                range: 28..57,
                kind: Test {
                    test_id: Path(
                        "test_mod::test_foo1",
                    ),
                    attr: TestAttr {
                        ignore: false,
                    },
                },
            },
        ]
        "###
                );
    }

    #[test]
    fn test_runnables_one_depth_layer_module() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        mod foo {
            mod test_mod {
                #[test]
                fn test_foo1() {}
            }
        }
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert_debug_snapshot!(&runnables,
        @r###"
        [
            Runnable {
                range: 23..85,
                kind: TestMod {
                    path: "foo::test_mod",
                },
            },
            Runnable {
                range: 46..79,
                kind: Test {
                    test_id: Path(
                        "foo::test_mod::test_foo1",
                    ),
                    attr: TestAttr {
                        ignore: false,
                    },
                },
            },
        ]
        "###
                );
    }

    #[test]
    fn test_runnables_multiple_depth_module() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        mod foo {
            mod bar {
                mod test_mod {
                    #[test]
                    fn test_foo1() {}
                }
            }
        }
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert_debug_snapshot!(&runnables,
        @r###"
        [
            Runnable {
                range: 41..115,
                kind: TestMod {
                    path: "foo::bar::test_mod",
                },
            },
            Runnable {
                range: 68..105,
                kind: Test {
                    test_id: Path(
                        "foo::bar::test_mod::test_foo1",
                    ),
                    attr: TestAttr {
                        ignore: false,
                    },
                },
            },
        ]
        "###
                );
    }

    #[test]
    fn test_runnables_no_test_function_in_module() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        mod test_mod {
            fn foo1() {}
        }
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert!(runnables.is_empty())
    }
}
<commit_msg>fix doctest inside impl block #4449<commit_after>//! FIXME: write short doc here

use hir::{AsAssocItem, Semantics};
use itertools::Itertools;
use ra_ide_db::RootDatabase;
use ra_syntax::{
    ast::{self, AstNode, AttrsOwner, ModuleItemOwner, NameOwner},
    match_ast, SyntaxNode, TextRange,
};

use crate::FileId;
use ast::DocCommentsOwner;
use std::fmt::Display;

#[derive(Debug)]
pub struct Runnable {
    pub range: TextRange,
    pub kind: RunnableKind,
}

#[derive(Debug)]
pub enum TestId {
    Name(String),
    Path(String),
}

impl Display for TestId {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            TestId::Name(name) => write!(f, "{}", name),
            TestId::Path(path) => write!(f, "{}", path),
        }
    }
}

#[derive(Debug)]
pub enum RunnableKind {
    Test { test_id: TestId, attr: TestAttr },
    TestMod { path: String },
    Bench { test_id: TestId },
    DocTest { test_id: TestId },
    Bin,
}

pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
    let sema = Semantics::new(db);
    let source_file = sema.parse(file_id);
    source_file.syntax().descendants().filter_map(|i| runnable(&sema, i)).collect()
}

fn runnable(sema: &Semantics<RootDatabase>, item: SyntaxNode) -> Option<Runnable> {
    match_ast! {
        match item {
            ast::FnDef(it) => runnable_fn(sema, it),
            ast::Module(it) => runnable_mod(sema, it),
            _ => None,
        }
    }
}

fn runnable_fn(sema: &Semantics<RootDatabase>, fn_def: ast::FnDef) -> Option<Runnable> {
    let name_string = fn_def.name()?.text().to_string();

    let kind = if name_string == "main" {
        RunnableKind::Bin
    } else {
        let test_id = if let Some(module) = sema.to_def(&fn_def).map(|def| def.module(sema.db)) {
            let def = sema.to_def(&fn_def)?;
            let impl_trait_name =
                def.as_assoc_item(sema.db).and_then(|assoc_item| {
                    match assoc_item.container(sema.db) {
                        hir::AssocItemContainer::Trait(trait_item) => {
                            Some(trait_item.name(sema.db).to_string())
                        }
                        hir::AssocItemContainer::ImplDef(impl_def) => impl_def
                            .target_ty(sema.db)
                            .as_adt()
                            .map(|adt| adt.name(sema.db).to_string()),
                    }
                });

            let path_iter = module
                .path_to_root(sema.db)
                .into_iter()
                .rev()
                .filter_map(|it| it.name(sema.db))
                .map(|name| name.to_string());

            let path = if let Some(impl_trait_name) = impl_trait_name {
                path_iter
                    .chain(std::iter::once(impl_trait_name))
                    .chain(std::iter::once(name_string))
                    .join("::")
            } else {
                path_iter.chain(std::iter::once(name_string)).join("::")
            };

            TestId::Path(path)
        } else {
            TestId::Name(name_string)
        };

        if has_test_related_attribute(&fn_def) {
            let attr = TestAttr::from_fn(&fn_def);
            RunnableKind::Test { test_id, attr }
        } else if fn_def.has_atom_attr("bench") {
            RunnableKind::Bench { test_id }
        } else if has_doc_test(&fn_def) {
            RunnableKind::DocTest { test_id }
        } else {
            return None;
        }
    };
    Some(Runnable { range: fn_def.syntax().text_range(), kind })
}

#[derive(Debug)]
pub struct TestAttr {
    pub ignore: bool,
}

impl TestAttr {
    fn from_fn(fn_def: &ast::FnDef) -> TestAttr {
        let ignore = fn_def
            .attrs()
            .filter_map(|attr| attr.simple_name())
            .any(|attribute_text| attribute_text == "ignore");
        TestAttr { ignore }
    }
}

/// This is a method with a heuristics to support test methods annotated with custom test annotations, such as
/// `#[test_case(...)]`, `#[tokio::test]` and similar.
/// Also a regular `#[test]` annotation is supported.
///
/// It may produce false positives, for example, `#[wasm_bindgen_test]` requires a different command to run the test,
/// but it's better than not to have the runnables for the tests at all.
fn has_test_related_attribute(fn_def: &ast::FnDef) -> bool {
    fn_def
        .attrs()
        .filter_map(|attr| attr.path())
        .map(|path| path.syntax().to_string().to_lowercase())
        .any(|attribute_text| attribute_text.contains("test"))
}

fn has_doc_test(fn_def: &ast::FnDef) -> bool {
    fn_def.doc_comment_text().map_or(false, |comment| comment.contains("```"))
}

fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> {
    let has_test_function = module
        .item_list()?
        .items()
        .filter_map(|it| match it {
            ast::ModuleItem::FnDef(it) => Some(it),
            _ => None,
        })
        .any(|f| has_test_related_attribute(&f));
    if !has_test_function {
        return None;
    }
    let range = module.syntax().text_range();
    let module = sema.to_def(&module)?;

    let path =
        module.path_to_root(sema.db).into_iter().rev().filter_map(|it| it.name(sema.db)).join("::");
    Some(Runnable { range, kind: RunnableKind::TestMod { path } })
}

#[cfg(test)]
mod tests {
    use insta::assert_debug_snapshot;

    use crate::mock_analysis::analysis_and_position;

    #[test]
    fn test_runnables() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        fn main() {}

        #[test]
        fn test_foo() {}

        #[test]
        #[ignore]
        fn test_foo() {}
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert_debug_snapshot!(&runnables,
        @r###"
        [
            Runnable {
                range: 1..21,
                kind: Bin,
            },
            Runnable {
                range: 22..46,
                kind: Test {
                    test_id: Path(
                        "test_foo",
                    ),
                    attr: TestAttr {
                        ignore: false,
                    },
                },
            },
            Runnable {
                range: 47..81,
                kind: Test {
                    test_id: Path(
                        "test_foo",
                    ),
                    attr: TestAttr {
                        ignore: true,
                    },
                },
            },
        ]
        "###
                );
    }

    #[test]
    fn test_runnables_doc_test() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        fn main() {}

        /// ```
        /// let x = 5;
        /// ```
        fn foo() {}
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert_debug_snapshot!(&runnables,
        @r###"
        [
            Runnable {
                range: 1..21,
                kind: Bin,
            },
            Runnable {
                range: 22..64,
                kind: DocTest {
                    test_id: Path(
                        "foo",
                    ),
                },
            },
        ]
        "###
                );
    }

    #[test]
    fn test_runnables_doc_test_in_impl() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        fn main() {}

        struct Data;
        impl Data {
            /// ```
            /// let x = 5;
            /// ```
            fn foo() {}
        }
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert_debug_snapshot!(&runnables,
        @r###"
        [
            Runnable {
                range: 1..21,
                kind: Bin,
            },
            Runnable {
                range: 52..106,
                kind: DocTest {
                    test_id: Path(
                        "Data::foo",
                    ),
                },
            },
        ]
        "###
                );
    }

    #[test]
    fn test_runnables_module() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        mod test_mod {
            #[test]
            fn test_foo1() {}
        }
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert_debug_snapshot!(&runnables,
        @r###"
        [
            Runnable {
                range: 1..59,
                kind: TestMod {
                    path: "test_mod",
                },
            },
            Runnable {
                range: 28..57,
                kind: Test {
                    test_id: Path(
                        "test_mod::test_foo1",
                    ),
                    attr: TestAttr {
                        ignore: false,
                    },
                },
            },
        ]
        "###
                );
    }

    #[test]
    fn test_runnables_one_depth_layer_module() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        mod foo {
            mod test_mod {
                #[test]
                fn test_foo1() {}
            }
        }
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert_debug_snapshot!(&runnables,
        @r###"
        [
            Runnable {
                range: 23..85,
                kind: TestMod {
                    path: "foo::test_mod",
                },
            },
            Runnable {
                range: 46..79,
                kind: Test {
                    test_id: Path(
                        "foo::test_mod::test_foo1",
                    ),
                    attr: TestAttr {
                        ignore: false,
                    },
                },
            },
        ]
        "###
                );
    }

    #[test]
    fn test_runnables_multiple_depth_module() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        mod foo {
            mod bar {
                mod test_mod {
                    #[test]
                    fn test_foo1() {}
                }
            }
        }
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert_debug_snapshot!(&runnables,
        @r###"
        [
            Runnable {
                range: 41..115,
                kind: TestMod {
                    path: "foo::bar::test_mod",
                },
            },
            Runnable {
                range: 68..105,
                kind: Test {
                    test_id: Path(
                        "foo::bar::test_mod::test_foo1",
                    ),
                    attr: TestAttr {
                        ignore: false,
                    },
                },
            },
        ]
        "###
                );
    }

    #[test]
    fn test_runnables_no_test_function_in_module() {
        let (analysis, pos) = analysis_and_position(
            r#"
        //- /lib.rs
        <|> //empty
        mod test_mod {
            fn foo1() {}
        }
        "#,
        );
        let runnables = analysis.runnables(pos.file_id).unwrap();
        assert!(runnables.is_empty())
    }
}
<|endoftext|>


<commit_before>/// RLE Lossless implementation taken from Pydicom
/// Copyright 2008-2021 pydicom authors.
/// License: <https://github.com/pydicom/pydicom/blob/master/LICENSE>
/// https://github.com/pydicom/pydicom/blob/master/pydicom/pixel_data_handlers/rle_handler.py
use byteordered::byteorder::{ByteOrder, LittleEndian};
use snafu::OptionExt;

use crate::adapters::{DecodeResult, EncodeResult, PixelDataObject, PixelRWAdapter};
use std::io::{self, Read, Seek};

use super::{CustomDecodeError, MissingAttribute, NotImplementedError};

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct RLELosslessAdapter;

/// Decode TS: 1.2.840.10008.1.2.5 (RLE Lossless)
impl PixelRWAdapter for RLELosslessAdapter {
    /// Decode RLE Lossless decoded dicom completely
    /// See http://dicom.nema.org/medical/Dicom/2018d/output/chtml/part05/chapter_G.html
    fn decode(&self, src: &dyn PixelDataObject, dst: &mut Vec<u8>) -> DecodeResult<()> {
        let cols = src.cols().context(MissingAttribute { name: "Columns" })?;
        let rows = src.rows().context(MissingAttribute { name: "Rows" })?;
        let samples_per_pixel = src.samples_per_pixel().context(MissingAttribute {
            name: "SamplesPerPixel",
        })?;
        let bits_allocated = src.bits_allocated().context(MissingAttribute {
            name: "BitsAllocated",
        })?;
        if bits_allocated != 8 && bits_allocated != 16 {
            CustomDecodeError {
                message: "BitsAllocated other than 8 or 16 is not supported",
            }
            .fail()?
        }
        // For RLE the number of fragments = number of frames
        // therefore, we can fetch the fragments one-by-one
        let nr_frames = src.number_of_fragments().context(CustomDecodeError {
            message: "Invalid pixel data, no fragments found",
        })? as usize;
        let bytes_per_sample = bits_allocated / 8;
        // `stride` it the total number of bytes for each sample plane
        let stride = bytes_per_sample * cols * rows;
        dst.resize((samples_per_pixel * stride) as usize * nr_frames, 0);

        // RLE encoded data is ordered like this (for 16-bit, 3 sample):
        //  Segment: 0     | 1     | 2     | 3     | 4     | 5
        //           R MSB | R LSB | G MSB | G LSB | B MSB | B LSB
        //  A segment contains only the MSB or LSB parts of all the sample pixels

        // To minimise the amount of array manipulation later, and to make things
        // faster we interleave each segment in a manner consistent with a planar
        // configuration of 1 (and use little endian byte ordering):
        //    All red samples             | All green samples           | All blue
        //    Pxl 1   Pxl 2   ... Pxl N   | Pxl 1   Pxl 2   ... Pxl N   | ...
        //    LSB MSB LSB MSB ... LSB MSB | LSB MSB LSB MSB ... LSB MSB | ...

        for i in 0..nr_frames {
            let fragment = &src.fragment(i).context(CustomDecodeError {
                message: "No pixel data found for frame",
            })?;
            let mut offsets = read_rle_header(fragment);
            offsets.push(fragment.len() as u32);

            for sample_number in 0..samples_per_pixel {
                for byte_offset in (0..bytes_per_sample).rev() {
                    // ii is 1, 0, 3, 2, 5, 4 for the example above
                    // This is where the segment order correction occurs
                    let ii = sample_number * bytes_per_sample + byte_offset;
                    let segment = &fragment
                        [offsets[ii as usize] as usize..offsets[(ii + 1) as usize] as usize];
                    let buff = io::Cursor::new(segment);
                    let (_, mut decoder) =
                        PackBitsReader::new(buff, segment.len()).map_err(|_| {
                            CustomDecodeError {
                                message: "Invalid RLE pixel data",
                            }
                            .build()
                        })?;
                    let mut decoded_segment: Vec<u8> = vec![0; (rows * cols) as usize];
                    decoder.read_exact(&mut decoded_segment).unwrap();

                    // Interleave pixels as described in the example above
                    let byte_offset = bytes_per_sample - byte_offset - 1;
                    let start = (samples_per_pixel as usize * stride as usize * i)
                        + byte_offset as usize
                        + (sample_number * stride) as usize;
                    let end = start + stride as usize;
                    for (decoded_index, dst_index) in
                        (start..end).step_by(bytes_per_sample as usize).enumerate()
                    {
                        dst[dst_index] = decoded_segment[decoded_index];
                    }
                }
            }
        }
        Ok(())
    }

    fn encode(&self, _src: &[u8], _dst: &mut Vec<u8>) -> EncodeResult<()> {
        NotImplementedError {}.fail()?
    }
}

// Read the RLE header and return the offsets
fn read_rle_header(fragment: &[u8]) -> Vec<u32> {
    let nr_segments = LittleEndian::read_u32(&fragment[0..4]);
    let mut offsets = vec![0; nr_segments as usize];
    LittleEndian::read_u32_into(&fragment[4..4 * (nr_segments + 1) as usize], &mut offsets);
    offsets
}

/// PackBits Reader from the image-tiff crate
/// Copyright 2018-2021 PistonDevelopers.
/// License: <https://github.com/image-rs/image-tiff/blob/master/LICENSE>
/// From: https://github.com/image-rs/image-tiff/blob/master/src/decoder/stream.rs
#[derive(Debug)]
pub struct PackBitsReader {
    buffer: io::Cursor<Vec<u8>>,
}

impl PackBitsReader {
    /// Wraps a reader
    pub fn new<R: Read + Seek>(
        mut reader: R,
        length: usize,
    ) -> io::Result<(usize, PackBitsReader)> {
        let mut buffer = Vec::new();
        let mut header: [u8; 1] = [0];
        let mut data: [u8; 1] = [0];

        let mut bytes_read = 0;
        while bytes_read < length {
            reader.read_exact(&mut header)?;
            bytes_read += 1;

            let h = header[0] as i8;
            if h >= -127 && h <= -1 {
                let new_len = buffer.len() + (1 - h as isize) as usize;
                reader.read_exact(&mut data)?;
                buffer.resize(new_len, data[0]);
                bytes_read += 1;
            } else if h >= 0 {
                let num_vals = h as usize + 1;
                let start = buffer.len();
                buffer.resize(start + num_vals, 0);
                reader.read_exact(&mut buffer[start..])?;
                bytes_read += num_vals
            } else {
                // h = -128 is a no-op.
            }
        }

        Ok((
            buffer.len(),
            PackBitsReader {
                buffer: io::Cursor::new(buffer),
            },
        ))
    }
}

impl Read for PackBitsReader {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.buffer.read(buf)
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_packbits() {
        let encoded = vec![
            0xFE, 0xAA, 0x02, 0x80, 0x00, 0x2A, 0xFD, 0xAA, 0x03, 0x80, 0x00, 0x2A, 0x22, 0xF7,
            0xAA,
        ];
        let encoded_len = encoded.len();

        let buff = io::Cursor::new(encoded);
        let (_, mut decoder) = PackBitsReader::new(buff, encoded_len).unwrap();

        let mut decoded = Vec::new();
        decoder.read_to_end(&mut decoded).unwrap();

        let expected = vec![
            0xAA, 0xAA, 0xAA, 0x80, 0x00, 0x2A, 0xAA, 0xAA, 0xAA, 0xAA, 0x80, 0x00, 0x2A, 0x22,
            0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
        ];
        assert_eq!(decoded, expected);
    }
}
<commit_msg>Apply suggestions from code review<commit_after>//! Support for RLE Lossless image decoding.
//!
//! implementation taken from Pydicom:
//! <https://github.com/pydicom/pydicom/blob/master/pydicom/pixel_data_handlers/rle_handler.py>
//!
//! Copyright 2008-2021 pydicom authors.
//!
//! License: <https://github.com/pydicom/pydicom/blob/master/LICENSE>
use byteordered::byteorder::{ByteOrder, LittleEndian};
use snafu::OptionExt;

use crate::adapters::{DecodeResult, EncodeResult, PixelDataObject, PixelRWAdapter};
use std::io::{self, Read, Seek};

use super::{CustomDecodeError, MissingAttribute, NotImplementedError};

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct RLELosslessAdapter;

/// Decode TS: 1.2.840.10008.1.2.5 (RLE Lossless)
impl PixelRWAdapter for RLELosslessAdapter {
    /// Decode the DICOM image from RLE Lossless completely.
    ///
    /// See <http://dicom.nema.org/medical/Dicom/2018d/output/chtml/part05/chapter_G.html>
    fn decode(&self, src: &dyn PixelDataObject, dst: &mut Vec<u8>) -> DecodeResult<()> {
        let cols = src.cols().context(MissingAttribute { name: "Columns" })?;
        let rows = src.rows().context(MissingAttribute { name: "Rows" })?;
        let samples_per_pixel = src.samples_per_pixel().context(MissingAttribute {
            name: "SamplesPerPixel",
        })?;
        let bits_allocated = src.bits_allocated().context(MissingAttribute {
            name: "BitsAllocated",
        })?;
        if bits_allocated != 8 && bits_allocated != 16 {
            CustomDecodeError {
                message: "BitsAllocated other than 8 or 16 is not supported",
            }
            .fail()?
        }
        // For RLE the number of fragments = number of frames
        // therefore, we can fetch the fragments one-by-one
        let nr_frames = src.number_of_fragments().context(CustomDecodeError {
            message: "Invalid pixel data, no fragments found",
        })? as usize;
        let bytes_per_sample = bits_allocated / 8;
        // `stride` it the total number of bytes for each sample plane
        let stride = bytes_per_sample * cols * rows;
        dst.resize((samples_per_pixel * stride) as usize * nr_frames, 0);

        // RLE encoded data is ordered like this (for 16-bit, 3 sample):
        //  Segment: 0     | 1     | 2     | 3     | 4     | 5
        //           R MSB | R LSB | G MSB | G LSB | B MSB | B LSB
        //  A segment contains only the MSB or LSB parts of all the sample pixels

        // To minimise the amount of array manipulation later, and to make things
        // faster we interleave each segment in a manner consistent with a planar
        // configuration of 1 (and use little endian byte ordering):
        //    All red samples             | All green samples           | All blue
        //    Pxl 1   Pxl 2   ... Pxl N   | Pxl 1   Pxl 2   ... Pxl N   | ...
        //    LSB MSB LSB MSB ... LSB MSB | LSB MSB LSB MSB ... LSB MSB | ...

        for i in 0..nr_frames {
            let fragment = &src.fragment(i).context(CustomDecodeError {
                message: "No pixel data found for frame",
            })?;
            let mut offsets = read_rle_header(fragment);
            offsets.push(fragment.len() as u32);

            for sample_number in 0..samples_per_pixel {
                for byte_offset in (0..bytes_per_sample).rev() {
                    // ii is 1, 0, 3, 2, 5, 4 for the example above
                    // This is where the segment order correction occurs
                    let ii = sample_number * bytes_per_sample + byte_offset;
                    let segment = &fragment
                        [offsets[ii as usize] as usize..offsets[(ii + 1) as usize] as usize];
                    let buff = io::Cursor::new(segment);
                    let (_, mut decoder) =
                        PackBitsReader::new(buff, segment.len()).map_err(|_| {
                            CustomDecodeError {
                                message: "Invalid RLE pixel data",
                            }
                            .build()
                        })?;
                    let mut decoded_segment: Vec<u8> = vec![0; (rows * cols) as usize];
                    decoder.read_exact(&mut decoded_segment).unwrap();

                    // Interleave pixels as described in the example above
                    let byte_offset = bytes_per_sample - byte_offset - 1;
                    let start = (samples_per_pixel as usize * stride as usize * i)
                        + byte_offset as usize
                        + (sample_number * stride) as usize;
                    let end = start + stride as usize;
                    for (decoded_index, dst_index) in
                        (start..end).step_by(bytes_per_sample as usize).enumerate()
                    {
                        dst[dst_index] = decoded_segment[decoded_index];
                    }
                }
            }
        }
        Ok(())
    }

    fn encode(&self, _src: &[u8], _dst: &mut Vec<u8>) -> EncodeResult<()> {
        NotImplementedError {}.fail()?
    }
}

// Read the RLE header and return the offsets
fn read_rle_header(fragment: &[u8]) -> Vec<u32> {
    let nr_segments = LittleEndian::read_u32(&fragment[0..4]);
    let mut offsets = vec![0; nr_segments as usize];
    LittleEndian::read_u32_into(&fragment[4..4 * (nr_segments + 1) as usize], &mut offsets);
    offsets
}

/// PackBits Reader from the image-tiff crate
/// Copyright 2018-2021 PistonDevelopers.
/// License: <https://github.com/image-rs/image-tiff/blob/master/LICENSE>
/// From: https://github.com/image-rs/image-tiff/blob/master/src/decoder/stream.rs
#[derive(Debug)]
pub struct PackBitsReader {
    buffer: io::Cursor<Vec<u8>>,
}

impl PackBitsReader {
    /// Wraps a reader
    pub fn new<R: Read + Seek>(
        mut reader: R,
        length: usize,
    ) -> io::Result<(usize, PackBitsReader)> {
        let mut buffer = Vec::new();
        let mut header: [u8; 1] = [0];
        let mut data: [u8; 1] = [0];

        let mut bytes_read = 0;
        while bytes_read < length {
            reader.read_exact(&mut header)?;
            bytes_read += 1;

            let h = header[0] as i8;
            if h >= -127 && h <= -1 {
                let new_len = buffer.len() + (1 - h as isize) as usize;
                reader.read_exact(&mut data)?;
                buffer.resize(new_len, data[0]);
                bytes_read += 1;
            } else if h >= 0 {
                let num_vals = h as usize + 1;
                let start = buffer.len();
                buffer.resize(start + num_vals, 0);
                reader.read_exact(&mut buffer[start..])?;
                bytes_read += num_vals
            } else {
                // h = -128 is a no-op.
            }
        }

        Ok((
            buffer.len(),
            PackBitsReader {
                buffer: io::Cursor::new(buffer),
            },
        ))
    }
}

impl Read for PackBitsReader {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.buffer.read(buf)
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_packbits() {
        let encoded = vec![
            0xFE, 0xAA, 0x02, 0x80, 0x00, 0x2A, 0xFD, 0xAA, 0x03, 0x80, 0x00, 0x2A, 0x22, 0xF7,
            0xAA,
        ];
        let encoded_len = encoded.len();

        let buff = io::Cursor::new(encoded);
        let (_, mut decoder) = PackBitsReader::new(buff, encoded_len).unwrap();

        let mut decoded = Vec::new();
        decoder.read_to_end(&mut decoded).unwrap();

        let expected = vec![
            0xAA, 0xAA, 0xAA, 0x80, 0x00, 0x2A, 0xAA, 0xAA, 0xAA, 0xAA, 0x80, 0x00, 0x2A, 0x22,
            0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
        ];
        assert_eq!(decoded, expected);
    }
}
<|endoftext|>


<commit_before>extern crate num;
extern crate rand;
extern crate time;
extern crate sync;

extern crate bignum = "bignum#0.1.1-pre";

use bignum::{BigUint, ToBigUint, RandBigInt};
use num::{div_mod_floor, Integer};
use std::num::{Zero, One, pow, Float, FromPrimitive, FromStrRadix};
use rand::{task_rng, Rng};
use rand::distributions::range::SampleRange;
use std::vec::Vec;
use std::iter;
use std::iter::{FromIterator};
use std::clone::Clone;
use std::ops::{Shr, BitAnd};
use std::bool;

use sync::Arc;

static pow_offsets : &'static[uint] = &[0u, 4u, 6u, 10u, 12u, 16u];

#[inline]
fn big<T: ToBigUint>(i : T) -> BigUint {
    i.to_biguint().unwrap()
}

// Source: https://gist.github.com/jsanders/8739134#file-generate_big_primes-rs-L35
fn mod_exp<T: Integer + Clone + Shr<uint,T> + BitAnd<T,T>>
    (base: &T, exponent: &T, modulus: &T) -> T {

    let (zero, one): (T, T) = (Zero::zero(), One::one());
    let mut result = one.clone();
    let mut baseAcc = base.clone();
    let mut exponentAcc = exponent.clone();

    while exponentAcc > zero {
        // Accumulate current base if current exponent bit is 1
        if (exponentAcc & one) == one {
            result = result.mul(&baseAcc);
            result = result.rem(modulus);
        }
        // Get next base by squaring
        baseAcc = baseAcc * baseAcc;
        baseAcc = baseAcc % *modulus;

        // Get next bit of exponent
        exponentAcc = exponentAcc.shr(&1);
    }
    result

}

// Rabin-Miller primality test, probabilistic
fn try_composite(a : &BigUint, d : &BigUint, n : &BigUint, s : &BigUint) -> bool {

    let one : BigUint = One::one();
    if mod_exp(a, d, n) == one {
        return false
    }
    let mut i = 0u;
    loop {
        if big(i) == *s {
            break
        }
        if mod_exp(a, &(pow(one+one, i) * *d), n) == *n-one {
            return false
        }
        i += 1;
    }
    true

}
fn rm_is_prime(n : &BigUint) -> bool {

    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let two = one + one;

    assert!(n >= &two);

    let mut s = zero.clone();
    let mut d = *n-one;
    let num_trials = 5;
    if n == &two {
        return true
    } else if n == &one || n.is_even() {
        return false
    } else {
        loop {
            let (quotient, remainder) = div_mod_floor(d.clone(), two.clone());
            if remainder == one { break }
            s = s + one;
            d = quotient;
        }
    }

    let mut rng = task_rng();
    for _ in range(0, num_trials) {
        let a = rng.gen_biguint_range(&two, n);
        if try_composite(&a, &d, n, &s) {
            return false
        }
    }
    true

}

fn fermat_is_prime(n : &BigUint) -> bool {
    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let two = one + one;

    if n == &two {
        true
    } else if n.is_even() {
        false
    } else if mod_exp(&two, &(n-one), n) == one {
        true
    } else {
        false
    }
}

fn is_valid_pow(prime : &BigUint) -> Option<BigUint> {
    for offset in [big(0u), big(4u), big(6u), big(10u), big(12u), big(16u)].iter() {
        if !fermat_is_prime(&(*prime + *offset)) {
            return None;
        }
    }
    Some(prime.clone())
}

// Simple sieve
fn simple_sieve(max_sieve : uint, verbose : bool) -> Vec<uint> {
    #[inline]
    fn int_sqrt(n: uint) -> uint { (n as f64).sqrt() as uint }

    let mut primes = Vec::from_elem(max_sieve+1, true);
    *primes.get_mut(0) = false;
    *primes.get_mut(1) = false;
    for prime in range(2, int_sqrt(max_sieve) + 1) {
        if *primes.get(prime) {
            for multiple in iter::range_step(prime * prime, max_sieve + 1, prime) {
                *primes.get_mut(multiple) = false
            }
            if verbose { println!("Sieved {}", prime) }
        }
    }
    if verbose { println!("Finished sieving") }
    range(2, max_sieve+1).filter(|&n| *primes.get(n)).collect()
}
fn candidate_killed_by(candidate : &BigUint, prime : &BigUint) -> bool {
    let zero : BigUint = Zero::zero();
    for &offset in pow_offsets.iter() {
        let o : BigUint = big(offset);
        if (*candidate + o) % *prime == zero {
            return true;
        }
    }
    false
}

fn add_next_prime (max_val : &BigUint, offsets : Vec<BigUint>,
    prime : BigUint, primorial : BigUint, min_val : BigUint) -> Vec<BigUint> {
    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let mut base : BigUint = zero.clone();
    let mut new_offsets : Vec<BigUint> = Vec::new();
    let mut counter = zero.clone();
    while counter < prime {
        if base + min_val > *max_val {
            break
        }
        for o in offsets.iter() {
            let val = min_val + base + *o;
            if val > *max_val {
                break
            }
            if !candidate_killed_by(&val, &prime) {
                new_offsets.push(val - min_val);
            }
        }
        base = base + primorial;
        counter = counter + one;
    }
    new_offsets
}

fn wheel_sieve(sieved : &Vec<uint>, base_val : &BigUint, max_val : &BigUint) -> Vec<BigUint> {
    let primorial_start : uint = 7u;
    let mut primorial : uint = 210u;  // 2*3*5*7
    let mut offsets : Vec<BigUint> = Vec::from_slice([big(97u)]);

    //let mut start_time = time::precise_time_s();
    let mut min_val : BigUint = Zero::zero();
    for &i in sieved.iter() {
        if i <= primorial_start {
            continue
        }
        min_val = (base_val / big(primorial)) * big(primorial);
        offsets = add_next_prime(max_val, offsets, big(i), big(primorial),
            min_val.clone());
        primorial = primorial * i;
    }
    //println!("Time to sieve sieve: {}", time::precise_time_s() - start_time);

    offsets.retain(|o| is_valid_pow(&(o+min_val)) != None);
    offsets
}

fn gen_prime(base_val : &BigUint, max_val : &BigUint, max_sieve : uint, verbose : bool) -> uint {
    let sieved = simple_sieve(max_sieve, verbose);
    let offsets = wheel_sieve(&sieved, base_val, max_val);
    offsets.len()
}

fn gen_prime_par(base_val : &BigUint, max_val : &BigUint, max_sieve : uint,
    num_tasks : uint, verbose : bool) -> uint {
    let sieved = Arc::new(simple_sieve(max_sieve, verbose));

    let mut count = 0;
    let (tx, rx) = channel();
    for i in range(0, num_tasks) {
        let start_val = base_val + (big(i) * (max_val-*base_val)) / big(num_tasks);
        let end_val = base_val + (big(i+1) * (max_val-*base_val)) / big(num_tasks);
        let child_tx = tx.clone();
        let child_sieved = sieved.clone();
        spawn(proc() {
            child_tx.send(wheel_sieve(child_sieved.deref(), &start_val, &end_val).len());
        });
    }

    for i in range(0, num_tasks) {
        count += rx.recv();
    }
    count
}

#[cfg(test)]
mod test_primes {
    use super::{big, gen_prime, simple_sieve};

    #[test]
    fn gen_prime_is_correct() {
        assert!(gen_prime(&big(0), &big(100000000), 29, false) == 81u);
    }

    #[test]
    fn simple_sieve_is_correct() {
        assert!(simple_sieve(&mut Vec::new(), 5000000, false).len() == 348513);
    }
}

fn main() {
    let args = std::os::args();
    let min_val = big(0);
    let max_val : BigUint = BigUint::from_str_radix("4294967296", 10).unwrap();
    if args.len() == 3 && args[1] == "-p".to_owned() {
        let num_tasks = from_str::<uint>(args[2]).unwrap();
        println!("{}", gen_prime_par(&min_val, &max_val, 50000, num_tasks, true));
    } else if args[1] == "-s".to_owned() {
        println!("{}", gen_prime(&min_val, &max_val, 50000, true));
    }
}
<commit_msg>Fast fast fast<commit_after>extern crate num;
extern crate rand;
extern crate sync;
extern crate time;

extern crate bignum = "bignum#0.1.1-pre";

use std::num::{Zero, One, pow, Float};
use std::vec::Vec;
use std::iter;
use std::clone::Clone;
use std::ops::{Shr, BitAnd};

use num::{div_mod_floor, Integer};
use rand::task_rng;
use sync::Arc;

use bignum::{BigUint, ToBigUint, RandBigInt};

static pow_offsets : &'static[uint] = &[0u, 4u, 6u, 10u, 12u, 16u];

#[inline]
fn big<T: ToBigUint>(i : T) -> BigUint {
    i.to_biguint().unwrap()
}

// Source: https://gist.github.com/jsanders/8739134#file-generate_big_primes-rs-L35
fn mod_exp<T: Integer + Clone + Shr<uint,T> + BitAnd<T,T>>
    (base: &T, exponent: &T, modulus: &T) -> T {

    let (zero, one): (T, T) = (Zero::zero(), One::one());
    let mut result = one.clone();
    let mut baseAcc = base.clone();
    let mut exponentAcc = exponent.clone();

    while exponentAcc > zero {
        // Accumulate current base if current exponent bit is 1
        if (exponentAcc & one) == one {
            result = result.mul(&baseAcc);
            result = result.rem(modulus);
        }
        // Get next base by squaring
        baseAcc = baseAcc * baseAcc;
        baseAcc = baseAcc % *modulus;

        // Get next bit of exponent
        exponentAcc = exponentAcc.shr(&1);
    }
    result

}

// Rabin-Miller primality test, probabilistic
fn try_composite(a : &BigUint, d : &BigUint, n : &BigUint, s : &BigUint) -> bool {

    let one : BigUint = One::one();
    if mod_exp(a, d, n) == one {
        return false
    }
    let mut i = 0u;
    loop {
        if big(i) == *s {
            break
        }
        if mod_exp(a, &(pow(one+one, i) * *d), n) == *n-one {
            return false
        }
        i += 1;
    }
    true

}
fn rm_is_prime(n : &BigUint) -> bool {

    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let two = one + one;

    assert!(n >= &two);

    let mut s = zero.clone();
    let mut d = *n-one;
    let num_trials = 5;
    if n == &two {
        return true
    } else if n == &one || n.is_even() {
        return false
    } else {
        loop {
            let (quotient, remainder) = div_mod_floor(d.clone(), two.clone());
            if remainder == one { break }
            s = s + one;
            d = quotient;
        }
    }

    let mut rng = task_rng();
    for _ in range(0, num_trials) {
        let a = rng.gen_biguint_range(&two, n);
        if try_composite(&a, &d, n, &s) {
            return false
        }
    }
    true

}

fn fermat_is_prime(n : &BigUint) -> bool {
    let one : BigUint = One::one();
    let two = one + one;

    if n == &two {
        true
    } else if n.is_even() {
        false
    } else if mod_exp(&two, &(n-one), n) == one {
        true
    } else {
        false
    }
}

fn is_valid_pow(prime : &BigUint) -> bool {
    for offset in [big(0u), big(4u), big(6u), big(10u), big(12u), big(16u)].iter() {
        if !fermat_is_prime(&(*prime + *offset)) {
            return false;
        }
    }
    true
}

fn is_valid_pow_rm(prime : &BigUint) -> bool {
    for offset in [big(0u), big(4u), big(6u), big(10u), big(12u), big(16u)].iter() {
        if !rm_is_prime(&(*prime + *offset)) {
            return false;
        }
    }
    true
}

// Simple sieve
fn simple_sieve(max_sieve : uint, verbose : bool) -> Vec<uint> {
    #[inline]
    fn int_sqrt(n: uint) -> uint { (n as f64).sqrt() as uint }

    let mut primes = Vec::from_elem(max_sieve+1, true);
    *primes.get_mut(0) = false;
    *primes.get_mut(1) = false;
    for prime in range(2, int_sqrt(max_sieve) + 1) {
        if *primes.get(prime) {
            for multiple in iter::range_step(prime * prime, max_sieve + 1, prime) {
                *primes.get_mut(multiple) = false
            }
            if verbose { println!("Sieved {}", prime) }
        }
    }
    if verbose { println!("Finished sieving") }
    range(2, max_sieve+1).filter(|&n| *primes.get(n)).collect()
}
fn candidate_killed_by(candidate : &BigUint, prime : &BigUint) -> bool {
    let zero : BigUint = Zero::zero();
    for &offset in pow_offsets.iter() {
        let o : BigUint = big(offset);
        if (*candidate + o) % *prime == zero {
            return true;
        }
    }
    false
}

fn add_next_prime (max_val : &BigUint, offsets : Vec<BigUint>,
    prime : BigUint, primorial : BigUint, min_val : BigUint) -> Vec<BigUint> {
    let (zero, one): (BigUint, BigUint) = (Zero::zero(), One::one());
    let mut base : BigUint = zero.clone();
    let mut new_offsets : Vec<BigUint> = Vec::new();
    let mut counter = zero.clone();
    while counter < prime {
        if base + min_val > *max_val {
            break
        }
        for o in offsets.iter() {
            let val = min_val + base + *o;
            if val > *max_val {
                break
            }
            if !candidate_killed_by(&val, &prime) {
                new_offsets.push(val - min_val);
            }
        }
        base = base + primorial;
        counter = counter + one;
    }
    new_offsets
}

fn wheel_sieve(sieved : &Vec<uint>, base_val : &BigUint, max_val : &BigUint) -> Option<BigUint> {
    let primorial_start : uint = 7u;
    let mut primorial : uint = 210u;  // 2*3*5*7
    let mut offsets : Vec<BigUint> = Vec::from_slice([big(97u)]);

    for &i in sieved.iter() {
        unsafe {
            if found_cluster {
                return None;
            }
        }
        if i <= primorial_start {
            continue
        }
        let min_val = (base_val / big(primorial)) * big(primorial);
        offsets = add_next_prime(max_val, offsets, big(i), big(primorial),
            min_val.clone());
        primorial = primorial * i;
        for o in offsets.iter() {
            unsafe {
                if found_cluster {
                    return None;
                }
            }
            let candidate = o + min_val;
            if is_valid_pow(&candidate) {
                if is_valid_pow_rm(&candidate) {
                    unsafe { found_cluster = true; }
                    return Some(candidate);
                }
            }
        }
    }
    None
}

fn gen_prime(base_val : &BigUint, max_val : &BigUint, max_sieve : uint, verbose : bool) -> Option<BigUint> {
    let sieved = simple_sieve(max_sieve, verbose);
    wheel_sieve(&sieved, base_val, max_val)
}

static mut found_cluster : bool = false;
fn gen_prime_par(base_val : &BigUint, max_val : &BigUint, max_sieve : uint,
    num_tasks : uint, verbose : bool) -> Option<BigUint> {
    let sieved = Arc::new(simple_sieve(max_sieve, verbose));

    let (tx, rx) = channel();
    let inc = (max_val - *base_val) / big(num_tasks);
    for i in range(0, num_tasks) {
        let start_val = base_val + big(i) * inc;
        let end_val = base_val + big(i+1) * inc;
        let child_tx = tx.clone();
        let child_sieved = sieved.clone();
        spawn(proc() {
            child_tx.send(wheel_sieve(child_sieved.deref(), &start_val, &end_val));
        });
    }
    let mut result = None;
    for _ in range(0, num_tasks) {
        match rx.recv() {
            None => continue,
            Some(v) => {
                result = Some(v);
                println!("Found candidate: {}", result);
            }
        }
    }
    unsafe { found_cluster = false; }
    result
}

#[cfg(test)]
mod test_primes {
    use super::{big, gen_prime, simple_sieve};

    #[test]
    fn gen_prime_is_correct() {
        assert!(gen_prime(&big(0), &big(100000000), 29, false) == 81u);
    }

    #[test]
    fn simple_sieve_is_correct() {
        assert!(simple_sieve(&mut Vec::new(), 5000000, false).len() == 348513);
    }
}

fn main() {
    let args = std::os::args();
    let min_val = big(0x123123123123000);
    let max_val : BigUint = BigUint::from_str_radix("123123123123ffff", 16).unwrap();
    if args.len() == 3 && args[1] == "-p".to_owned() {
        let num_tasks = from_str::<uint>(args[2]).unwrap();
        println!("{}", gen_prime_par(&min_val, &max_val, 50000, num_tasks, true));
    } else if args[1] == "-s".to_owned() {
        println!("{}", gen_prime(&min_val, &max_val, 50000, true));
    }
}
<|endoftext|>


<commit_before>// A version of pstree targetting linux written in rust!
//
// This is based on the following exercise from the excellent
// book "The Linux Programming Interface" by Michael Kerridsk.
//
//----------------------------------------------------------------------
//
// Write a program that draws a tree showing the hierarchical
// parent-child relationships of all processes on the system, going all
// the way back to init.  For each process, the program should display
// the process ID and the command being executed.  The output of the
// program should be similar to that produced by pstree(1), although it
// does need not to be as sophisticated.  The parent of each process on
// the system can be found by inspecing the PPid: line of all of the
// /proc/PID/status files on the system.  Be careful to handle the
// possibilty that a process's parent (and thus its /proc/PID directory)
// disappears during the scan of all /proc/PID directories.

// Implementation Notes
// --------------------
// The linux /proc filesystem is a virtual filesystem that provides information
// about processes running on a linux system among other things.  The /proc
// filesystem contains a directory, /proc/<pid>, for each running process in
// the system.
//
// Each process directory has a status file with contents including a bunch
// of different items, notably the process name and its parent process id (ppid).
// And with that information, we can build the process tree.

#![feature(old_io)]
#![feature(old_path)]

use std::old_io::fs::PathExtensions;
use std::old_io::fs;
use std::old_io::File;
use std::old_io::BufferedReader;

#[derive(Clone,Debug)]
struct ProcessRecord {
    name: String,
    pid: i32,
    ppid: i32,
}

#[derive(Clone,Debug)]
struct ProcessTreeNode {
    record: ProcessRecord,  // the node owns the associated record
    children: Vec<ProcessTreeNode>, // nodes own their children
}

#[derive(Clone,Debug)]
struct ProcessTree {
    root: ProcessTreeNode, // tree owns ref to root node
}

impl ProcessTreeNode {
    // constructor
    fn new(record : &ProcessRecord) -> ProcessTreeNode {
        ProcessTreeNode { record: (*record).clone(), children: Vec::new() }
    }
}

// Given a status file path, return a hashmap with the following form:
// pid -> ProcessRecord
fn get_process_record(status_path: &Path) -> Option<ProcessRecord> {
    let mut pid : Option<i32> = None;
    let mut ppid : Option<i32> = None;
    let mut name : Option<String> = None;

    let mut status_file = BufferedReader::new(File::open(status_path));
    for line in status_file.lines() {
        let unwrapped = line.unwrap(); // need a new lifeline
        let parts : Vec<&str> = unwrapped[..].splitn(2, ':').collect();
        if parts.len() == 2 {
            let key = parts[0].trim();
            let value = parts[1].trim();
            match key {
                "Name" => name = Some(value.to_string()),
                "Pid" => pid = value.parse().ok(),
                "PPid" => ppid = value.parse().ok(),
                _ => (),
            }
        }
    }

    return if pid.is_some() && ppid.is_some() && name.is_some() {
        Some(ProcessRecord { name: name.unwrap(), pid: pid.unwrap(), ppid: ppid.unwrap() })
    } else {
        None
    }
}

// build a simple struct (ProcessRecord) for each process
fn get_process_records() -> Vec<ProcessRecord> {
    let proc_directory = Path::new("/proc");

    // find potential process directories under /proc
    let proc_directory_contents = fs::readdir(&proc_directory).unwrap();
    proc_directory_contents.iter().filter_map(|entry| {
        if entry.is_dir() {
            let status_path = entry.join("status");
            if status_path.exists() {
                return get_process_record(&status_path)
            }
        }
        None
    }).collect()
}

fn populate_node(node : &mut ProcessTreeNode, records: &Vec<ProcessRecord>) {
    // populate the node by finding its children... recursively
    let pid = node.record.pid; // avoid binding node as immutable in closure
    node.children.extend(
        records.iter().filter_map(|record| {
            if record.ppid == pid {
                let mut child = ProcessTreeNode::new(record);
                populate_node(&mut child, records);
                Some(child)
            } else {
                None
            }
        })
    )
}

fn build_process_tree() -> ProcessTree {
    let records = get_process_records();
    let mut tree = ProcessTree {
        root : ProcessTreeNode::new(
            &ProcessRecord {
                name: "/".to_string(),
                pid: 0,
                ppid: -1
            })
    };

    // recursively populate all nodes in the tree starting from root (pid 0)
    {
        let root = &mut tree.root;
        populate_node(root, &records);
    }
    tree
}

fn print_node(node : &ProcessTreeNode, indent_level : i32) {
    // print indentation
    for _ in (0..indent_level) {
        print!("  ");
    }
    println!("- {} #{}", node.record.name, node.record.pid);
    for child in node.children.iter() {
        print_node(child, indent_level + 1);  // recurse
    }
}

fn main() {
    let ptree = build_process_tree();
    print_node(&(ptree.root), 0)
}
<commit_msg>Use hashmap for O(n) instead of O(n^2) tree building from records<commit_after>// A version of pstree targetting linux written in rust!
//
// This is based on the following exercise from the excellent
// book "The Linux Programming Interface" by Michael Kerridsk.
//
//----------------------------------------------------------------------
//
// Write a program that draws a tree showing the hierarchical
// parent-child relationships of all processes on the system, going all
// the way back to init.  For each process, the program should display
// the process ID and the command being executed.  The output of the
// program should be similar to that produced by pstree(1), although it
// does need not to be as sophisticated.  The parent of each process on
// the system can be found by inspecing the PPid: line of all of the
// /proc/PID/status files on the system.  Be careful to handle the
// possibilty that a process's parent (and thus its /proc/PID directory)
// disappears during the scan of all /proc/PID directories.

// Implementation Notes
// --------------------
// The linux /proc filesystem is a virtual filesystem that provides information
// about processes running on a linux system among other things.  The /proc
// filesystem contains a directory, /proc/<pid>, for each running process in
// the system.
//
// Each process directory has a status file with contents including a bunch
// of different items, notably the process name and its parent process id (ppid).
// And with that information, we can build the process tree.

#![feature(old_io)]
#![feature(old_path)]
#![feature(std_misc)] // hash_map::Entry

use std::old_io::fs::PathExtensions;
use std::old_io::fs;
use std::old_io::File;
use std::old_io::BufferedReader;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;

#[derive(Clone,Debug)]
struct ProcessRecord {
    name: String,
    pid: i32,
    ppid: i32,
}

#[derive(Clone,Debug)]
struct ProcessTreeNode {
    record: ProcessRecord,  // the node owns the associated record
    children: Vec<ProcessTreeNode>, // nodes own their children
}

#[derive(Clone,Debug)]
struct ProcessTree {
    root: ProcessTreeNode, // tree owns ref to root node
}

impl ProcessTreeNode {
    // constructor
    fn new(record : &ProcessRecord) -> ProcessTreeNode {
        ProcessTreeNode { record: (*record).clone(), children: Vec::new() }
    }
}

// Given a status file path, return a hashmap with the following form:
// pid -> ProcessRecord
fn get_process_record(status_path: &Path) -> Option<ProcessRecord> {
    let mut pid : Option<i32> = None;
    let mut ppid : Option<i32> = None;
    let mut name : Option<String> = None;

    let mut status_file = BufferedReader::new(File::open(status_path));
    for line in status_file.lines() {
        let unwrapped = line.unwrap(); // need a new lifeline
        let parts : Vec<&str> = unwrapped[..].splitn(2, ':').collect();
        if parts.len() == 2 {
            let key = parts[0].trim();
            let value = parts[1].trim();
            match key {
                "Name" => name = Some(value.to_string()),
                "Pid" => pid = value.parse().ok(),
                "PPid" => ppid = value.parse().ok(),
                _ => (),
            }
        }
    }

    return if pid.is_some() && ppid.is_some() && name.is_some() {
        Some(ProcessRecord { name: name.unwrap(), pid: pid.unwrap(), ppid: ppid.unwrap() })
    } else {
        None
    }
}

// build a simple struct (ProcessRecord) for each process
fn get_process_records() -> Vec<ProcessRecord> {
    let proc_directory = Path::new("/proc");

    // find potential process directories under /proc
    let proc_directory_contents = fs::readdir(&proc_directory).unwrap();
    proc_directory_contents.iter().filter_map(|entry| {
        if entry.is_dir() {
            let status_path = entry.join("status");
            if status_path.exists() {
                return get_process_record(&status_path)
            }
        }
        None
    }).collect()
}

fn populate_node_helper(node: &mut ProcessTreeNode, pid_map: &HashMap<i32, &ProcessRecord>, ppid_map: &HashMap<i32, Vec<i32>>) {
    let pid = node.record.pid; // avoid binding node as immutable in closure
    let child_nodes = &mut node.children;
    match ppid_map.get(&pid) {
        Some(children) => {
            child_nodes.extend(children.iter().map(|child_pid| {
                let record = pid_map[*child_pid];
                let mut child = ProcessTreeNode::new(record);
                populate_node_helper(&mut child, pid_map, ppid_map);
                child
            }));
        },
        None => {},
    }
}

fn populate_node(node : &mut ProcessTreeNode, records: &Vec<ProcessRecord>) {
    // O(n): build a mapping of pids to vectors of children.  That is, each
    // key is a pid and its value is a vector of the whose parent pid is the key
    let mut ppid_map : HashMap<i32, Vec<i32>> = HashMap::new();
    let mut pid_map : HashMap<i32, &ProcessRecord> = HashMap::new();
    for record in records.iter() {
        // entry returns either a vacant or occupied entry.  If vacant,
        // we insert a new vector with this records pid.  If occupied,
        // we push this record's pid onto the vec
        pid_map.insert(record.pid, record);
        match ppid_map.entry(record.ppid) {
            Vacant(entry) => { entry.insert(vec![record.pid]); },
            Occupied(mut entry) => { entry.get_mut().push(record.pid); },
        };
    }

    // With the data structures built, it is off to the races
    populate_node_helper(node, &pid_map, &ppid_map);
}

fn build_process_tree() -> ProcessTree {
    let records = get_process_records();
    let mut tree = ProcessTree {
        root : ProcessTreeNode::new(
            &ProcessRecord {
                name: "/".to_string(),
                pid: 0,
                ppid: -1
            })
    };

    // recursively populate all nodes in the tree starting from root (pid 0)
    {
        let root = &mut tree.root;
        populate_node(root, &records);
    }
    tree
}

fn print_node(node : &ProcessTreeNode, indent_level : i32) {
    // print indentation
    for _ in (0..indent_level) {
        print!("  ");
    }
    println!("- {} #{}", node.record.name, node.record.pid);
    for child in node.children.iter() {
        print_node(child, indent_level + 1);  // recurse
    }
}

fn main() {
    let ptree = build_process_tree();
    print_node(&(ptree.root), 0)
}
<|endoftext|>