<commit_before>extern crate num;

use std::f32::consts;

use num::complex::{Complex, Complex32};

fn main() {
    let degree = 3;

    for root in roots_of_unity(degree) {
        println!("{}", root);
    }
}

fn roots_of_unity(degree: usize) -> impl Iterator<Item=Complex32> {
    (0..degree)
        .map(move |el| {
            Complex::<f32>::from_polar(&1f32, &(2f32 * consts::PI * (el as f32) / (degree as f32)))
        })
}

#[test]
fn test_result() {
    let expected = vec![
        Complex::new(1f32, 0.),
        Complex::new(-0.5, 0.866025),
        Complex::new(-0.5, -0.866025),
    ];

    for (root, exp) in roots_of_unity(3).zip(expected.iter()) {
        assert!((root - exp).norm() < 1e-6);
    }
}
<commit_msg>Run rustfmt<commit_after>extern crate num;

use std::f32::consts;

use num::complex::{Complex, Complex32};

fn main() {
    let degree = 3;

    for root in roots_of_unity(degree) {
        println!("{}", root);
    }
}

fn roots_of_unity(degree: usize) -> impl Iterator<Item = Complex32> {
    (0..degree).map(move |el| {
        Complex::<f32>::from_polar(&1f32, &(2f32 * consts::PI * (el as f32) / (degree as f32)))
    })
}

#[test]
fn test_result() {
    let expected = vec![
        Complex::new(1f32, 0.),
        Complex::new(-0.5, 0.866025),
        Complex::new(-0.5, -0.866025),
    ];

    for (root, exp) in roots_of_unity(3).zip(expected.iter()) {
        assert!((root - exp).norm() < 1e-6);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;
extern crate docopt;
extern crate image;
extern crate imageproc;
extern crate gpx;
extern crate geo;
extern crate chrono;
extern crate rayon;
extern crate rand;

use std::error::Error;
use std::fs;
use std::fs::File;
use std::io::{BufReader, Write};
use std::path;

use docopt::Docopt;
use gpx::read;
use gpx::{Gpx, Track};
use geo::Point;
use image::ImageBuffer;
use rayon::prelude::*;

const USAGE: &'static str = "
Generate video from GPX files.

Usage:
  derivers [options] <top-lat> <left-lng> <bottom-lat> <right-lng> <width> <height> <directory>

Options:
";

#[derive(Debug, Deserialize)]
struct CommandArgs {
    arg_top_lat: f64,
    arg_left_lng: f64,
    arg_bottom_lat: f64,
    arg_right_lng: f64,
    arg_width: u32,
    arg_height: u32,
    arg_directory: String,
}

type ScreenPoint = (u32, u32);

struct Heatmap {
    top_left: Point<f64>,
    bottom_right: Point<f64>,
    width: u32,
    height: u32,
    heatmap: Vec<u32>,
    start: ScreenPoint,
    max_value: u32,
}

impl Heatmap {
    pub fn from(args: &CommandArgs) -> Heatmap {
        // h == w * (top - bottom) / (right - left)
        let ratio = (args.arg_top_lat - args.arg_bottom_lat) /
            (args.arg_right_lng - args.arg_left_lng);

        let width = args.arg_width as u32;
        let height = ((args.arg_width as f64) * ratio) as u32;

        println!("Computed height: {:?}", height);

        let size = (width * height) as usize;

        let mut heatmap = Vec::with_capacity(size);
        for _ in 0..size {
            heatmap.push(0);
        }

        Heatmap {
            top_left: Point::new(args.arg_left_lng, args.arg_top_lat),
            bottom_right: Point::new(args.arg_right_lng, args.arg_bottom_lat),
            width: width,
            height: height,
            heatmap: heatmap,
            start: (0, 0),
            max_value: 0,
        }
    }

    pub fn as_image(&self) -> image::DynamicImage {
        let color_map = self.heatmap
            .clone()
            .into_par_iter()
            .map(|px| ((px % 255) as u8, 0, 0))
            .collect::<Vec<_>>();

        let size = (self.width * self.height * 3) as usize;
        let mut pixels = Vec::with_capacity(size);

        for pxl in color_map.iter() {
            pixels.extend_from_slice(&[pxl.0, pxl.1, pxl.2]);
        }

        let buffer = ImageBuffer::from_raw(self.width, self.height, pixels).unwrap();
        image::ImageRgb8(buffer)
    }

    pub fn save_frame<W: Write>(&self, writer: &mut W, fmt: image::ImageFormat) {
        let image = self.as_image();
        image.save(writer, fmt).unwrap();
    }

    #[inline]
    fn get_pixel_mut(&mut self, point: &ScreenPoint) -> Option<&mut u32> {
        if point.0 >= self.width || point.1 >= self.height {
            return None;
        }

        let index = (point.0 + (point.1 * self.width)) as usize;
        Some(&mut self.heatmap[index])
    }

    #[inline]
    pub fn add_point(&mut self, point: &ScreenPoint) {

        // Lol rust?
        let px = {
            let px = self.get_pixel_mut(point).unwrap();
            // TODO: Logarithmic growth
            *px += 1;
            *px
        };

        self.max_value = self.max_value.max(px);
    }

    #[allow(dead_code)]
    pub fn decay(&mut self, amount: u8) {
        self.heatmap.par_iter_mut().for_each(|px| { *px -= 1; });
    }

    // Using simple equirectangular projection for now. Returns None if point
    // is off screen.
    pub fn project_to_screen(&self, coord: &Point<f64>) -> Option<ScreenPoint> {
        // lng is x pos
        let x_pos = self.top_left.lng() - coord.lng();
        let y_pos = self.top_left.lat() - coord.lat();

        let x_offset = x_pos / (self.top_left.lng() - self.bottom_right.lng());
        let y_offset = y_pos / (self.top_left.lat() - self.bottom_right.lat());

        let (x, y) = (
            (x_offset * self.width as f64),
            (y_offset * self.height as f64),
        );

        if (x < 0.0 || x as u32 >= self.width) || (y < 0.0 || y as u32 >= self.height) {
            None
        } else {
            Some((x as u32, y as u32))
        }
    }
}

#[derive(Debug)]
struct Activity {
    name: String,
    date: chrono::DateTime<chrono::Utc>,
    track_points: Vec<Point<f64>>,
}

fn parse_gpx(path: &path::PathBuf) -> Result<Activity, Box<Error>> {
    println!("Parsing {:?}", path);

    let file = File::open(path)?;
    let reader = BufReader::new(file);

    let gpx: Gpx = read(reader)?;

    // Nothing to do if there are no tracks
    if gpx.tracks.len() == 0 {
        return Err(Box::from("file has no tracks"));
    } else if gpx.tracks.len() > 1 {
        println!("Warning! more than 1 track, just taking first");
    }

    let track: &Track = &gpx.tracks[0];

    let mut activity = Activity {
        name: track.name.clone().unwrap_or(String::from("Untitled")),
        date: chrono::Utc::now(),
        track_points: vec![],
    };

    if let Some(metadata) = gpx.metadata {
        if let Some(time) = metadata.time {
            activity.date = time;
        }
    }

    // Append all the waypoints.
    for seg in track.segments.iter() {
        let points = seg.points.iter().map(|ref wpt| wpt.point());
        activity.track_points.extend(points);
    }

    if activity.track_points.len() == 0 {
        Err(Box::from("No track points"))
    } else {
        Ok(activity)
    }
}

fn main() {
    let args: CommandArgs = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());

    println!("{:?}", args);

    let mut map = Heatmap::from(&args);

    let paths: Vec<path::PathBuf> = fs::read_dir(args.arg_directory)
        .unwrap()
        .into_iter()
        .map(|p| p.unwrap().path())
        .collect();

    let mut activities: Vec<Activity> = paths
        .into_par_iter()
        .filter_map(|ref p| parse_gpx(p).ok())
        .collect();

    activities.sort_by_key(|a| a.date);

    // let ppm_file = &mut File::create("heatmap.ppm").unwrap();
    let png_file = &mut File::create("heatmap.png").unwrap();
    let mut counter = 0;

    for act in activities {
        println!("Activity: {:?}", act.name);

        let pixels: Vec<ScreenPoint> = act.track_points
            .into_iter()
            .filter_map(|ref pt| map.project_to_screen(pt))
            .collect();

        // counter = 0;
        for ref point in pixels.into_iter() {
            map.start = point.clone();

            map.add_point(point);

            counter += 1;

            // if counter % (3 * 150) == 0 {
            //     map.save_frame(ppm_file, image::PPM);
            // }
        }

        // FIXME: this is pretty ugly.
        // map.decay(1);
    }

    map.save_frame(png_file, image::PNG);
}
<commit_msg>Logarithmic color gradient<commit_after>#[macro_use]
extern crate serde_derive;
extern crate docopt;
extern crate image;
extern crate imageproc;
extern crate gpx;
extern crate geo;
extern crate chrono;
extern crate rayon;
extern crate rand;

use std::error::Error;
use std::fs;
use std::fs::File;
use std::io::{BufReader, Write};
use std::path;

use docopt::Docopt;
use gpx::read;
use gpx::{Gpx, Track};
use geo::Point;
use image::ImageBuffer;
use rayon::prelude::*;

const USAGE: &'static str = "
Generate video from GPX files.

Usage:
  derivers [options] <top-lat> <left-lng> <bottom-lat> <right-lng> <width> <height> <directory>

Options:
";

#[derive(Debug, Deserialize)]
struct CommandArgs {
    arg_top_lat: f64,
    arg_left_lng: f64,
    arg_bottom_lat: f64,
    arg_right_lng: f64,
    arg_width: u32,
    arg_height: u32,
    arg_directory: String,
}

type ScreenPoint = (u32, u32);

struct Heatmap {
    top_left: Point<f64>,
    bottom_right: Point<f64>,
    width: u32,
    height: u32,
    heatmap: Vec<u32>,
    start: ScreenPoint,
    max_value: u32,
}

impl Heatmap {
    pub fn from(args: &CommandArgs) -> Heatmap {
        // h == w * (top - bottom) / (right - left)
        let ratio = (args.arg_top_lat - args.arg_bottom_lat) /
            (args.arg_right_lng - args.arg_left_lng);

        let width = args.arg_width as u32;
        let height = ((args.arg_width as f64) * ratio) as u32;

        println!("Computed height: {:?}", height);

        let size = (width * height) as usize;

        let mut heatmap = Vec::with_capacity(size);
        for _ in 0..size {
            heatmap.push(0);
        }

        Heatmap {
            top_left: Point::new(args.arg_left_lng, args.arg_top_lat),
            bottom_right: Point::new(args.arg_right_lng, args.arg_bottom_lat),
            width: width,
            height: height,
            heatmap: heatmap,
            start: (0, 0),
            max_value: 0,
        }
    }

    pub fn as_image(&self) -> image::DynamicImage {
        let color_map = self.heatmap
            .clone()
            .into_par_iter()
            .map(|count| {
                if count == 0 {
                    return (0, 0, 0);
                }

                let heat = (count as f64).log(self.max_value as f64) * 255.0;
                let heat = heat.max(75.0) as u8;
                (heat, heat / 4, heat / 2)
            })
            .collect::<Vec<_>>();

        let size = (self.width * self.height * 3) as usize;
        let mut pixels = Vec::with_capacity(size);

        for pxl in color_map.iter() {
            pixels.extend_from_slice(&[pxl.0, pxl.1, pxl.2]);
        }

        let buffer = ImageBuffer::from_raw(self.width, self.height, pixels).unwrap();
        image::ImageRgb8(buffer)
    }

    pub fn save_frame<W: Write>(&self, writer: &mut W, fmt: image::ImageFormat) {
        let image = self.as_image();
        image.save(writer, fmt).unwrap();
    }

    #[inline]
    fn get_pixel_mut(&mut self, point: &ScreenPoint) -> Option<&mut u32> {
        if point.0 >= self.width || point.1 >= self.height {
            return None;
        }

        let index = (point.0 + (point.1 * self.width)) as usize;
        Some(&mut self.heatmap[index])
    }

    #[inline]
    pub fn add_point(&mut self, point: &ScreenPoint) {

        // FIXME: lol rust?
        let px = {
            let px = self.get_pixel_mut(point).unwrap();
            *px += 1;
            *px
        };

        self.max_value = self.max_value.max(px);
    }

    #[allow(dead_code)]
    pub fn decay(&mut self, amount: u32) {
        self.heatmap.par_iter_mut().for_each(|px| if *px > amount {
            *px -= amount;
        } else {
            *px = 0;
        });
    }

    // Using simple equirectangular projection for now. Returns None if point
    // is off screen.
    pub fn project_to_screen(&self, coord: &Point<f64>) -> Option<ScreenPoint> {
        // lng is x pos
        let x_pos = self.top_left.lng() - coord.lng();
        let y_pos = self.top_left.lat() - coord.lat();

        let x_offset = x_pos / (self.top_left.lng() - self.bottom_right.lng());
        let y_offset = y_pos / (self.top_left.lat() - self.bottom_right.lat());

        let (x, y) = (
            (x_offset * self.width as f64),
            (y_offset * self.height as f64),
        );

        if (x < 0.0 || x as u32 >= self.width) || (y < 0.0 || y as u32 >= self.height) {
            None
        } else {
            Some((x as u32, y as u32))
        }
    }
}

#[derive(Debug)]
struct Activity {
    name: String,
    date: chrono::DateTime<chrono::Utc>,
    track_points: Vec<Point<f64>>,
}

fn parse_gpx(path: &path::PathBuf) -> Result<Activity, Box<Error>> {
    println!("Parsing {:?}", path);

    let file = File::open(path)?;
    let reader = BufReader::new(file);

    let gpx: Gpx = read(reader)?;

    // Nothing to do if there are no tracks
    if gpx.tracks.len() == 0 {
        return Err(Box::from("file has no tracks"));
    } else if gpx.tracks.len() > 1 {
        println!("Warning! more than 1 track, just taking first");
    }

    let track: &Track = &gpx.tracks[0];

    let mut activity = Activity {
        name: track.name.clone().unwrap_or(String::from("Untitled")),
        date: chrono::Utc::now(),
        track_points: vec![],
    };

    if let Some(metadata) = gpx.metadata {
        if let Some(time) = metadata.time {
            activity.date = time;
        }
    }

    // Append all the waypoints.
    for seg in track.segments.iter() {
        let points = seg.points.iter().map(|ref wpt| wpt.point());
        activity.track_points.extend(points);
    }

    if activity.track_points.len() == 0 {
        Err(Box::from("No track points"))
    } else {
        Ok(activity)
    }
}

fn main() {
    let args: CommandArgs = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());

    println!("{:?}", args);

    let mut map = Heatmap::from(&args);

    let paths: Vec<path::PathBuf> = fs::read_dir(args.arg_directory)
        .unwrap()
        .into_iter()
        .map(|p| p.unwrap().path())
        .collect();

    let mut activities: Vec<Activity> = paths
        .into_par_iter()
        .filter_map(|ref p| parse_gpx(p).ok())
        .collect();

    activities.sort_by_key(|a| a.date);

    let ppm_file = &mut File::create("heatmap.ppm").unwrap();
    let png_file = &mut File::create("heatmap.png").unwrap();
    let mut counter;

    for act in activities {
        println!("Activity: {:?}", act.name);

        let pixels: Vec<ScreenPoint> = act.track_points
            .into_iter()
            .filter_map(|ref pt| map.project_to_screen(pt))
            .collect();

        counter = 0;
        for ref point in pixels.into_iter() {
            map.start = point.clone();

            map.add_point(point);

            counter += 1;

            if counter % (5 * 150) == 0 {
                map.save_frame(ppm_file, image::ImageFormat::PNM);
            }
        }

        // FIXME: this is pretty ugly.
        // map.decay(1);
    }

    map.save_frame(png_file, image::PNG);
}
<|endoftext|>


<commit_before>use std::ptr;
use std::str;
use std::ffi::CString;

use gl;
use gl::types::*;

#[cfg(target_family = "windows")]
pub use windows::gl_render::{init_opengl, create_gl_context, swap_buffers};

pub static VERTEX_SHADER_SRC: &'static str = "\
#version 150                            \n\
                                        \n\
in vec4 vertexPos;                      \n\
                                        \n\
void main(void)                         \n\
{                                       \n\
    gl_Position = vertexPos;            \n\
}";

pub static FRAGMENT_SHADER_SRC: &'static str = "\
#version 150                              \n\
                                          \n\
out vec4 fragmentColor;                   \n\
                                          \n\
void main(void)                           \n\
{                                         \n\
    fragmentColor = vec4(1, 0, 0, 1);     \n\
}";

pub struct Mesh;

impl Mesh {
    pub fn new() -> Mesh {
        Mesh
    }
}

pub fn draw_mesh(mesh: &Mesh) {
    unsafe {
        // TODO rebind the buffers or whatever

        gl::ClearColor(0.3, 0.3, 0.3, 1.0);
        gl::Clear(gl::COLOR_BUFFER_BIT);

        // Draw a triangle from the 3 vertices
        gl::DrawArrays(gl::TRIANGLE_FAN, 0, 5);

        swap_buffers(); // TODO don't swap buffers after every draw
    }
}

pub fn compile_shader(src: &str, ty: GLenum) -> GLuint {
    unsafe {
        let shader = gl::CreateShader(ty);

        // Attempt to compile the shader
        let c_str = CString::new(src.as_bytes());
        gl::ShaderSource(shader, 1, &c_str.unwrap().as_ptr(), ptr::null());
        gl::CompileShader(shader);

        // Get the compile status
        let mut status = gl::FALSE as GLint;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = Vec::with_capacity(len as usize);
            buf.set_len((len as usize) - 1); // subtract 1 to skip the trailing null character
            gl::GetShaderInfoLog(shader, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
            panic!("{}", str::from_utf8(buf.as_slice()).ok().expect("ShaderInfoLog not valid utf8"));
        }

        shader
    }
}

pub fn link_program(vs: GLuint, fs: GLuint) -> GLuint {
    unsafe {
        let program = gl::CreateProgram();
        gl::AttachShader(program, vs);
        gl::AttachShader(program, fs);
        gl::LinkProgram(program);

        // Get the link status
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len: GLint = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = Vec::with_capacity(len as usize);
            buf.set_len((len as usize) - 1); // subtract 1 to skip the trailing null character
            gl::GetProgramInfoLog(program, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
            panic!("{}", str::from_utf8(buf.as_slice()).ok().expect("ProgramInfoLog not valid utf8"));
        }
        program
    }
}
<commit_msg>Use Raw Strings for Shader Literals<commit_after>use std::ptr;
use std::str;
use std::ffi::CString;

use gl;
use gl::types::*;

// reexport platform-specific versions of functions
#[cfg(target_family = "windows")]
pub use windows::gl_render::{init_opengl, create_gl_context, swap_buffers};

pub static VERTEX_SHADER_SRC: &'static str = r#"
#version 150

in vec4 vertexPos;

void main(void)
{
    gl_Position = vertexPos;
}"#;

pub static FRAGMENT_SHADER_SRC: &'static str = r#"
#version 150

out vec4 fragmentColor;

void main(void)
{
    fragmentColor = vec4(1, 0, 0, 1);
}"#;

pub struct Mesh;

impl Mesh {
    pub fn new() -> Mesh {
        Mesh
    }
}

pub fn draw_mesh(mesh: &Mesh) {
    unsafe {
        // TODO rebind the buffers or whatever

        gl::ClearColor(0.3, 0.3, 0.3, 1.0);
        gl::Clear(gl::COLOR_BUFFER_BIT);

        // Draw a triangle from the 3 vertices
        gl::DrawArrays(gl::TRIANGLE_FAN, 0, 5);

        swap_buffers(); // TODO don't swap buffers after every draw
    }
}

pub fn compile_shader(src: &str, ty: GLenum) -> GLuint {
    unsafe {
        let shader = gl::CreateShader(ty);

        // Attempt to compile the shader
        let c_str = CString::new(src.as_bytes());
        gl::ShaderSource(shader, 1, &c_str.unwrap().as_ptr(), ptr::null());
        gl::CompileShader(shader);

        // Get the compile status
        let mut status = gl::FALSE as GLint;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = Vec::with_capacity(len as usize);
            buf.set_len((len as usize) - 1); // subtract 1 to skip the trailing null character
            gl::GetShaderInfoLog(shader, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
            panic!("{}", str::from_utf8(buf.as_slice()).ok().expect("ShaderInfoLog not valid utf8"));
        }

        shader
    }
}

pub fn link_program(vs: GLuint, fs: GLuint) -> GLuint {
    unsafe {
        let program = gl::CreateProgram();
        gl::AttachShader(program, vs);
        gl::AttachShader(program, fs);
        gl::LinkProgram(program);

        // Get the link status
        let mut status = gl::FALSE as GLint;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

        // Fail on error
        if status != (gl::TRUE as GLint) {
            let mut len: GLint = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
            let mut buf = Vec::with_capacity(len as usize);
            buf.set_len((len as usize) - 1); // subtract 1 to skip the trailing null character
            gl::GetProgramInfoLog(program, len, ptr::null_mut(), buf.as_mut_ptr() as *mut GLchar);
            panic!("{}", str::from_utf8(buf.as_slice()).ok().expect("ProgramInfoLog not valid utf8"));
        }
        program
    }
}
<|endoftext|>


<commit_before>/* This file is part of Grust, GObject introspection bindings for Rust
 *
 * Copyright (C) 2013  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

extern mod grust (name="grust", vers="0.1");
extern mod gio (name="grust-Gio", vers="2.0");

// We have to do this because of an rpath problem with crates linking to
// foreign libraries
pub extern mod grustna {
}

#[test]
fn main() {
    grust::init();
    let f = &gio::File::new_for_path("/dev/null") as &gio::File;
    assert!(f.get_path().to_str() == ~"/dev/null");
}
<commit_msg>Added an ignored test for off-stack calls<commit_after>/* This file is part of Grust, GObject introspection bindings for Rust
 *
 * Copyright (C) 2013  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

extern mod grust (name="grust", vers="0.1");
extern mod gio (name="grust-Gio", vers="2.0");

// We have to do this because of an rpath problem with crates linking to
// foreign libraries
pub extern mod grustna {
}

#[test]
fn simple() {
    grust::init();
    let f = &gio::File::new_for_path("/dev/null") as &gio::File;
    assert!(f.get_path().to_str() == ~"/dev/null");
}

// Crashes due to https://github.com/mozilla/rust/issues/5882
#[test]
#[ignore]
fn off_stack() {
    grust::init();
    let f = ~gio::File::new_for_path("/dev/null") as ~gio::File;
    do task::try {
        let p = f.get_path();
        assert!(p.to_str() == ~"/dev/null");
    };
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

pub fn can_arrange(arr: Vec<i32>, k: i32) -> bool {
    if arr.len() == 2 {
        return arr.iter().all(|v| v % k == 0);
    }

    let arr = arr.into_iter().map(|v| v % k).collect::<Vec<i32>>();

    dbg!(&arr);

    let mut count_table: HashMap<i32, usize> = HashMap::new();

    arr.iter().for_each(|v| {
        let en = count_table.entry(*v).or_insert(0);
        *en += 1;
    });

    dbg!(&count_table);

    for &kk in count_table.keys() {
        if kk == 0 {
            continue;
        }

        let count = if let Some(count) = count_table.get(&kk) {
            count
        } else {
            return false;
        };

        let pair_count = if let Some(count) = count_table.get(&(k - kk)) {
            count
        } else {
            return false;
        };

        if *pair_count != *count {
            return false;
        }
    }

    true
}

fn main() {
    assert!(can_arrange(vec![1, 2, 3, 4, 5, 10, 6, 7, 8, 9], 5));
    assert!(can_arrange(vec![1, 2, 3, 4, 5, 6], 7));
    assert!(!can_arrange(vec![1, 2, 3, 4, 5, 6], 10));
    assert!(can_arrange(vec![10, -10], 2));
    assert!(can_arrange(vec![-1, 1, -2, 2, -3, 3, -4, 4], 3));
}
<commit_msg>new methond<commit_after>use std::collections::HashMap;

pub fn can_arrange(arr: Vec<i32>, k: i32) -> bool {
    let mut table = HashMap::new();

    for num in arr {
        let m = num.rem_euclid(k);
        let cm = (-num).rem_euclid(k);

        //dbg!(&m, &cm);

        if let None = table.get(&cm) {
            let en = table.entry(m).or_insert(0);
            *en += 1;
        } else {
            let en = table.get_mut(&cm).unwrap();
            *en -= 1;
            if *en == 0 {
                table.remove(&cm);
            }
        }
    }

    //dbg!(&table);

    if table.len() == 0 {
        true
    } else {
        false
    }
}

fn main() {
    assert!(can_arrange(vec![1, 2, 3, 4, 5, 10, 6, 7, 8, 9], 5));
    assert!(can_arrange(vec![1, 2, 3, 4, 5, 6], 7));
    assert!(!can_arrange(vec![1, 2, 3, 4, 5, 6], 10));
    assert!(can_arrange(vec![10, -10], 2));
    assert!(can_arrange(vec![-1, 1, -2, 2, -3, 3, -4, 4], 3));
}
<|endoftext|>


<commit_before>use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
use once_cell::sync::Lazy;
use std::collections::HashMap;

use crate::clip_path::ClipPath;
use crate::filters::{
    blend::FeBlend,
    color_matrix::FeColorMatrix,
    component_transfer::{FeComponentTransfer, FeFuncA, FeFuncB, FeFuncG, FeFuncR},
    composite::FeComposite,
    convolve_matrix::FeConvolveMatrix,
    displacement_map::FeDisplacementMap,
    flood::FeFlood,
    gaussian_blur::FeGaussianBlur,
    image::FeImage,
    light::{
        light_source::FeDistantLight, light_source::FePointLight, light_source::FeSpotLight,
        lighting::FeDiffuseLighting, lighting::FeSpecularLighting,
    },
    merge::{FeMerge, FeMergeNode},
    morphology::FeMorphology,
    offset::FeOffset,
    tile::FeTile,
    turbulence::FeTurbulence,
};

use crate::filter::Filter;
use crate::gradient::{LinearGradient, RadialGradient, Stop};
use crate::image::Image;
use crate::link::Link;
use crate::marker::Marker;
use crate::mask::Mask;
use crate::node::*;
use crate::pattern::Pattern;
use crate::property_bag::PropertyBag;
use crate::shapes::{Circle, Ellipse, Line, Path, Polygon, Polyline, Rect};
use crate::structure::{Group, NonRendering, Svg, Switch, Symbol, Use};
use crate::style::Style;
use crate::text::{TRef, TSpan, Text};

macro_rules! n {
    ($name:ident, $node_type:ident) => {
        pub fn $name(element_name: &QualName, id: Option<&str>, class: Option<&str>) -> RsvgNode {
            RsvgNode::new(NodeData::new(
                NodeType::$node_type,
                element_name,
                id,
                class,
                Box::new(<$node_type>::default()),
            ))
        }
    };
}

#[cfg_attr(rustfmt, rustfmt_skip)]
mod creators {
    use super::*;

    n!(create_circle,                   Circle);
    n!(create_clip_path,                ClipPath);
    n!(create_defs,                     NonRendering);
    n!(create_ellipse,                  Ellipse);
    n!(create_fe_blend,                 FeBlend);
    n!(create_fe_color_matrix,          FeColorMatrix);
    n!(create_fe_component_transfer,    FeComponentTransfer);
    n!(create_fe_func_a,                FeFuncA);
    n!(create_fe_func_b,                FeFuncB);
    n!(create_fe_func_g,                FeFuncG);
    n!(create_fe_func_r,                FeFuncR);
    n!(create_fe_composite,             FeComposite);
    n!(create_fe_convolve_matrix,       FeConvolveMatrix);
    n!(create_fe_diffuse_lighting,      FeDiffuseLighting);
    n!(create_fe_distant_light,         FeDistantLight);
    n!(create_fe_displacement_map,      FeDisplacementMap);
    n!(create_fe_flood,                 FeFlood);
    n!(create_fe_gaussian_blur,         FeGaussianBlur);
    n!(create_fe_image,                 FeImage);
    n!(create_fe_merge,                 FeMerge);
    n!(create_fe_merge_node,            FeMergeNode);
    n!(create_fe_morphology,            FeMorphology);
    n!(create_fe_offset,                FeOffset);
    n!(create_fe_point_light,           FePointLight);
    n!(create_fe_specular_lighting,     FeSpecularLighting);
    n!(create_fe_spot_light,            FeSpotLight);
    n!(create_fe_tile,                  FeTile);
    n!(create_fe_turbulence,            FeTurbulence);
    n!(create_filter,                   Filter);
    n!(create_group,                    Group);
    n!(create_image,                    Image);
    n!(create_line,                     Line);
    n!(create_linear_gradient,          LinearGradient);
    n!(create_link,                     Link);
    n!(create_marker,                   Marker);
    n!(create_mask,                     Mask);
    n!(create_non_rendering,            NonRendering);
    n!(create_path,                     Path);
    n!(create_pattern,                  Pattern);
    n!(create_polygon,                  Polygon);
    n!(create_polyline,                 Polyline);
    n!(create_radial_gradient,          RadialGradient);
    n!(create_rect,                     Rect);
    n!(create_stop,                     Stop);
    n!(create_style,                    Style);
    n!(create_svg,                      Svg);
    n!(create_switch,                   Switch);
    n!(create_symbol,                   Symbol);
    n!(create_text,                     Text);
    n!(create_tref,                     TRef);
    n!(create_tspan,                    TSpan);
    n!(create_use,                      Use);

    /* Hack to make multiImage sort-of work
     *
     * disabled for now, as markup5ever doesn't have local names for
     * multiImage, subImage, subImageRef.  Maybe we can just... create them ourselves?
     *
     * Is multiImage even in SVG2?
     */
    /*
    n!(create_multi_image,              Switch);
    n!(create_sub_image,                Group);
n!(create_sub_image_ref,                Image);
    */
}

use creators::*;

type NodeCreateFn = fn(element_name: &QualName, id: Option<&str>, class: Option<&str>) -> RsvgNode;

macro_rules! c {
    ($hashset:expr, $str_name:expr, $supports_class:expr, $fn_name:ident) => {
        $hashset.insert($str_name, ($supports_class, $fn_name as NodeCreateFn));
    };
}

// Lines in comments are elements that we don't support.
#[cfg_attr(rustfmt, rustfmt_skip)]
static NODE_CREATORS: Lazy<HashMap<&'static str, (bool, NodeCreateFn)>> = Lazy::new(|| {
    let mut h = HashMap::new();
    // name, supports_class, create_fn
    c!(h, "a",                   true,  create_link);
    /* c!(h, "altGlyph",         true,  ); */
    /* c!(h, "altGlyphDef",      false, ); */
    /* c!(h, "altGlyphItem",     false, ); */
    /* c!(h, "animate",          false, ); */
    /* c!(h, "animateColor",     false, ); */
    /* c!(h, "animateMotion",    false, ); */
    /* c!(h, "animateTransform", false, ); */
    c!(h, "circle",              true,  create_circle);
    c!(h, "clipPath",            true,  create_clip_path);
    /* c!(h, "color-profile",    false, ); */
    /* c!(h, "cursor",           false, ); */
    c!(h, "defs",                true,  create_defs);
    /* c!(h, "desc",             true,  ); */
    c!(h, "ellipse",             true,  create_ellipse);
    c!(h, "feBlend",             true,  create_fe_blend);
    c!(h, "feColorMatrix",       true,  create_fe_color_matrix);
    c!(h, "feComponentTransfer", true,  create_fe_component_transfer);
    c!(h, "feComposite",         true,  create_fe_composite);
    c!(h, "feConvolveMatrix",    true,  create_fe_convolve_matrix);
    c!(h, "feDiffuseLighting",   true,  create_fe_diffuse_lighting);
    c!(h, "feDisplacementMap",   true,  create_fe_displacement_map);
    c!(h, "feDistantLight",      false, create_fe_distant_light);
    c!(h, "feFuncA",             false, create_fe_func_a);
    c!(h, "feFuncB",             false, create_fe_func_b);
    c!(h, "feFuncG",             false, create_fe_func_g);
    c!(h, "feFuncR",             false, create_fe_func_r);
    c!(h, "feFlood",             true,  create_fe_flood);
    c!(h, "feGaussianBlur",      true,  create_fe_gaussian_blur);
    c!(h, "feImage",             true,  create_fe_image);
    c!(h, "feMerge",             true,  create_fe_merge);
    c!(h, "feMergeNode",         false, create_fe_merge_node);
    c!(h, "feMorphology",        true,  create_fe_morphology);
    c!(h, "feOffset",            true,  create_fe_offset);
    c!(h, "fePointLight",        false, create_fe_point_light);
    c!(h, "feSpecularLighting",  true,  create_fe_specular_lighting);
    c!(h, "feSpotLight",         false, create_fe_spot_light);
    c!(h, "feTile",              true,  create_fe_tile);
    c!(h, "feTurbulence",        true,  create_fe_turbulence);
    c!(h, "filter",              true,  create_filter);
    /* c!(h, "font",             true,  ); */
    /* c!(h, "font-face",        false, ); */
    /* c!(h, "font-face-format", false, ); */
    /* c!(h, "font-face-name",   false, ); */
    /* c!(h, "font-face-src",    false, ); */
    /* c!(h, "font-face-uri",    false, ); */
    /* c!(h, "foreignObject",    true,  ); */
    c!(h, "g",                   true,  create_group);
    /* c!(h, "glyph",            true,  ); */
    /* c!(h, "glyphRef",         true,  ); */
    /* c!(h, "hkern",            false, ); */
    c!(h, "image",               true,  create_image);
    c!(h, "line",                true,  create_line);
    c!(h, "linearGradient",      true,  create_linear_gradient);
    c!(h, "marker",              true,  create_marker);
    c!(h, "mask",                true,  create_mask);
    /* c!(h, "metadata",         false, ); */
    /* c!(h, "missing-glyph",    true,  ); */
    /* c!(h, "mpath",            false, ); */
    /* c!(h, "multiImage",          false, create_multi_image); */
    c!(h, "path",                true,  create_path);
    c!(h, "pattern",             true,  create_pattern);
    c!(h, "polygon",             true,  create_polygon);
    c!(h, "polyline",            true,  create_polyline);
    c!(h, "radialGradient",      true,  create_radial_gradient);
    c!(h, "rect",                true,  create_rect);
    /* c!(h, "script",           false, ); */
    /* c!(h, "set",              false, ); */
    c!(h, "stop",                true,  create_stop);
    c!(h, "style",               false, create_style);
    /* c!(h, "subImage",            false, create_sub_image); */
    /* c!(h, "subImageRef",         false, create_sub_image_ref); */
    c!(h, "svg",                 true,  create_svg);
    c!(h, "switch",              true,  create_switch);
    c!(h, "symbol",              true,  create_symbol);
    c!(h, "text",                true,  create_text);
    /* c!(h, "textPath",         true,  ); */
    /* c!(h, "title",            true,  ); */
    c!(h, "tref",                true,  create_tref);
    c!(h, "tspan",               true,  create_tspan);
    c!(h, "use",                 true,  create_use);
    /* c!(h, "view",             false, ); */
    /* c!(h, "vkern",            false, ); */
    h
});

pub fn create_node(name: &QualName, pbag: &PropertyBag) -> RsvgNode {
    let mut id = None;
    let mut class = None;

    for (attr, value) in pbag.iter() {
        match attr.expanded() {
            expanded_name!("", "id") => id = Some(value),
            expanded_name!(svg "class") => class = Some(value),
            _ => (),
        }
    }

    let (supports_class, create_fn) = if name.ns == ns!(svg) {
        match NODE_CREATORS.get(name.local.as_ref()) {
            // hack in the SVG namespace for supported element names
            Some(&(supports_class, create_fn)) => (supports_class, create_fn),

            // Whenever we encounter a node we don't understand, represent it as a
            // non-rendering node.  This is like a group, but it doesn't do any rendering of
            // children.  The effect is that we will ignore all children of unknown elements.
            None => (true, create_non_rendering as NodeCreateFn),
        }
    } else {
        (true, create_non_rendering as NodeCreateFn)
    };

    if !supports_class {
        class = None;
    };

    create_fn(name, id, class)
}
<commit_msg>create_node: remove a macro, leverage FromIterator for the HashMap<commit_after>use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
use once_cell::sync::Lazy;
use std::collections::HashMap;

use crate::clip_path::ClipPath;
use crate::filters::{
    blend::FeBlend,
    color_matrix::FeColorMatrix,
    component_transfer::{FeComponentTransfer, FeFuncA, FeFuncB, FeFuncG, FeFuncR},
    composite::FeComposite,
    convolve_matrix::FeConvolveMatrix,
    displacement_map::FeDisplacementMap,
    flood::FeFlood,
    gaussian_blur::FeGaussianBlur,
    image::FeImage,
    light::{
        light_source::FeDistantLight, light_source::FePointLight, light_source::FeSpotLight,
        lighting::FeDiffuseLighting, lighting::FeSpecularLighting,
    },
    merge::{FeMerge, FeMergeNode},
    morphology::FeMorphology,
    offset::FeOffset,
    tile::FeTile,
    turbulence::FeTurbulence,
};

use crate::filter::Filter;
use crate::gradient::{LinearGradient, RadialGradient, Stop};
use crate::image::Image;
use crate::link::Link;
use crate::marker::Marker;
use crate::mask::Mask;
use crate::node::*;
use crate::pattern::Pattern;
use crate::property_bag::PropertyBag;
use crate::shapes::{Circle, Ellipse, Line, Path, Polygon, Polyline, Rect};
use crate::structure::{Group, NonRendering, Svg, Switch, Symbol, Use};
use crate::style::Style;
use crate::text::{TRef, TSpan, Text};

macro_rules! n {
    ($name:ident, $node_type:ident) => {
        pub fn $name(element_name: &QualName, id: Option<&str>, class: Option<&str>) -> RsvgNode {
            RsvgNode::new(NodeData::new(
                NodeType::$node_type,
                element_name,
                id,
                class,
                Box::new(<$node_type>::default()),
            ))
        }
    };
}

#[cfg_attr(rustfmt, rustfmt_skip)]
mod creators {
    use super::*;

    n!(create_circle,                   Circle);
    n!(create_clip_path,                ClipPath);
    n!(create_defs,                     NonRendering);
    n!(create_ellipse,                  Ellipse);
    n!(create_fe_blend,                 FeBlend);
    n!(create_fe_color_matrix,          FeColorMatrix);
    n!(create_fe_component_transfer,    FeComponentTransfer);
    n!(create_fe_func_a,                FeFuncA);
    n!(create_fe_func_b,                FeFuncB);
    n!(create_fe_func_g,                FeFuncG);
    n!(create_fe_func_r,                FeFuncR);
    n!(create_fe_composite,             FeComposite);
    n!(create_fe_convolve_matrix,       FeConvolveMatrix);
    n!(create_fe_diffuse_lighting,      FeDiffuseLighting);
    n!(create_fe_distant_light,         FeDistantLight);
    n!(create_fe_displacement_map,      FeDisplacementMap);
    n!(create_fe_flood,                 FeFlood);
    n!(create_fe_gaussian_blur,         FeGaussianBlur);
    n!(create_fe_image,                 FeImage);
    n!(create_fe_merge,                 FeMerge);
    n!(create_fe_merge_node,            FeMergeNode);
    n!(create_fe_morphology,            FeMorphology);
    n!(create_fe_offset,                FeOffset);
    n!(create_fe_point_light,           FePointLight);
    n!(create_fe_specular_lighting,     FeSpecularLighting);
    n!(create_fe_spot_light,            FeSpotLight);
    n!(create_fe_tile,                  FeTile);
    n!(create_fe_turbulence,            FeTurbulence);
    n!(create_filter,                   Filter);
    n!(create_group,                    Group);
    n!(create_image,                    Image);
    n!(create_line,                     Line);
    n!(create_linear_gradient,          LinearGradient);
    n!(create_link,                     Link);
    n!(create_marker,                   Marker);
    n!(create_mask,                     Mask);
    n!(create_non_rendering,            NonRendering);
    n!(create_path,                     Path);
    n!(create_pattern,                  Pattern);
    n!(create_polygon,                  Polygon);
    n!(create_polyline,                 Polyline);
    n!(create_radial_gradient,          RadialGradient);
    n!(create_rect,                     Rect);
    n!(create_stop,                     Stop);
    n!(create_style,                    Style);
    n!(create_svg,                      Svg);
    n!(create_switch,                   Switch);
    n!(create_symbol,                   Symbol);
    n!(create_text,                     Text);
    n!(create_tref,                     TRef);
    n!(create_tspan,                    TSpan);
    n!(create_use,                      Use);

    /* Hack to make multiImage sort-of work
     *
     * disabled for now, as markup5ever doesn't have local names for
     * multiImage, subImage, subImageRef.  Maybe we can just... create them ourselves?
     *
     * Is multiImage even in SVG2?
     */
    /*
    n!(create_multi_image,              Switch);
    n!(create_sub_image,                Group);
n!(create_sub_image_ref,                Image);
    */
}

use creators::*;

type NodeCreateFn = fn(element_name: &QualName, id: Option<&str>, class: Option<&str>) -> RsvgNode;

// Lines in comments are elements that we don't support.
#[cfg_attr(rustfmt, rustfmt_skip)]
static NODE_CREATORS: Lazy<HashMap<&'static str, (bool, NodeCreateFn)>> = Lazy::new(|| {
    let creators_table: Vec<(&str, bool, NodeCreateFn)> = vec![
        // name, supports_class, create_fn
        ("a",                   true,  create_link),
        /* ("altGlyph",         true,  ), */
        /* ("altGlyphDef",      false, ), */
        /* ("altGlyphItem",     false, ), */
        /* ("animate",          false, ), */
        /* ("animateColor",     false, ), */
        /* ("animateMotion",    false, ), */
        /* ("animateTransform", false, ), */
        ("circle",              true,  create_circle),
        ("clipPath",            true,  create_clip_path),
        /* ("color-profile",    false, ), */
        /* ("cursor",           false, ), */
        ("defs",                true,  create_defs),
        /* ("desc",             true,  ), */
        ("ellipse",             true,  create_ellipse),
        ("feBlend",             true,  create_fe_blend),
        ("feColorMatrix",       true,  create_fe_color_matrix),
        ("feComponentTransfer", true,  create_fe_component_transfer),
        ("feComposite",         true,  create_fe_composite),
        ("feConvolveMatrix",    true,  create_fe_convolve_matrix),
        ("feDiffuseLighting",   true,  create_fe_diffuse_lighting),
        ("feDisplacementMap",   true,  create_fe_displacement_map),
        ("feDistantLight",      false, create_fe_distant_light),
        ("feFuncA",             false, create_fe_func_a),
        ("feFuncB",             false, create_fe_func_b),
        ("feFuncG",             false, create_fe_func_g),
        ("feFuncR",             false, create_fe_func_r),
        ("feFlood",             true,  create_fe_flood),
        ("feGaussianBlur",      true,  create_fe_gaussian_blur),
        ("feImage",             true,  create_fe_image),
        ("feMerge",             true,  create_fe_merge),
        ("feMergeNode",         false, create_fe_merge_node),
        ("feMorphology",        true,  create_fe_morphology),
        ("feOffset",            true,  create_fe_offset),
        ("fePointLight",        false, create_fe_point_light),
        ("feSpecularLighting",  true,  create_fe_specular_lighting),
        ("feSpotLight",         false, create_fe_spot_light),
        ("feTile",              true,  create_fe_tile),
        ("feTurbulence",        true,  create_fe_turbulence),
        ("filter",              true,  create_filter),
        /* ("font",             true,  ), */
        /* ("font-face",        false, ), */
        /* ("font-face-format", false, ), */
        /* ("font-face-name",   false, ), */
        /* ("font-face-src",    false, ), */
        /* ("font-face-uri",    false, ), */
        /* ("foreignObject",    true,  ), */
        ("g",                   true,  create_group),
        /* ("glyph",            true,  ), */
        /* ("glyphRef",         true,  ), */
        /* ("hkern",            false, ), */
        ("image",               true,  create_image),
        ("line",                true,  create_line),
        ("linearGradient",      true,  create_linear_gradient),
        ("marker",              true,  create_marker),
        ("mask",                true,  create_mask),
        /* ("metadata",         false, ), */
        /* ("missing-glyph",    true,  ), */
        /* ("mpath",            false, ), */
        /* ("multiImage",       false, create_multi_image), */
        ("path",                true,  create_path),
        ("pattern",             true,  create_pattern),
        ("polygon",             true,  create_polygon),
        ("polyline",            true,  create_polyline),
        ("radialGradient",      true,  create_radial_gradient),
        ("rect",                true,  create_rect),
        /* ("script",           false, ), */
        /* ("set",              false, ), */
        ("stop",                true,  create_stop),
        ("style",               false, create_style),
        /* ("subImage",         false, create_sub_image), */
        /* ("subImageRef",      false, create_sub_image_ref), */
        ("svg",                 true,  create_svg),
        ("switch",              true,  create_switch),
        ("symbol",              true,  create_symbol),
        ("text",                true,  create_text),
        /* ("textPath",         true,  ), */
        /* ("title",            true,  ), */
        ("tref",                true,  create_tref),
        ("tspan",               true,  create_tspan),
        ("use",                 true,  create_use),
        /* ("view",             false, ), */
        /* ("vkern",            false, ), */
    ];

    creators_table.into_iter().map(|(n, s, f)| (n, (s, f))).collect()
});

pub fn create_node(name: &QualName, pbag: &PropertyBag) -> RsvgNode {
    let mut id = None;
    let mut class = None;

    for (attr, value) in pbag.iter() {
        match attr.expanded() {
            expanded_name!("", "id") => id = Some(value),
            expanded_name!(svg "class") => class = Some(value),
            _ => (),
        }
    }

    let (supports_class, create_fn) = if name.ns == ns!(svg) {
        match NODE_CREATORS.get(name.local.as_ref()) {
            // hack in the SVG namespace for supported element names
            Some(&(supports_class, create_fn)) => (supports_class, create_fn),

            // Whenever we encounter a node we don't understand, represent it as a
            // non-rendering node.  This is like a group, but it doesn't do any rendering of
            // children.  The effect is that we will ignore all children of unknown elements.
            None => (true, create_non_rendering as NodeCreateFn),
        }
    } else {
        (true, create_non_rendering as NodeCreateFn)
    };

    if !supports_class {
        class = None;
    };

    create_fn(name, id, class)
}
<|endoftext|>


<commit_before>use fortanix_sgx_abi::Tcs;

use super::abi::thread;

use super::waitqueue::{try_lock_or_false, NotifiedTcs, SpinMutex, WaitQueue, WaitVariable};

pub struct Mutex {
    inner: SpinMutex<WaitVariable<bool>>,
}

pub type MovableMutex = Box<Mutex>;

// Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
impl Mutex {
    pub const fn new() -> Mutex {
        Mutex { inner: SpinMutex::new(WaitVariable::new(false)) }
    }

    #[inline]
    pub unsafe fn init(&mut self) {}

    #[inline]
    pub unsafe fn lock(&self) {
        let mut guard = self.inner.lock();
        if *guard.lock_var() {
            // Another thread has the lock, wait
            WaitQueue::wait(guard, || {})
        // Another thread has passed the lock to us
        } else {
            // We are just now obtaining the lock
            *guard.lock_var_mut() = true;
        }
    }

    #[inline]
    pub unsafe fn unlock(&self) {
        let guard = self.inner.lock();
        if let Err(mut guard) = WaitQueue::notify_one(guard) {
            // No other waiters, unlock
            *guard.lock_var_mut() = false;
        } else {
            // There was a thread waiting, just pass the lock
        }
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        let mut guard = try_lock_or_false!(self.inner);
        if *guard.lock_var() {
            // Another thread has the lock
            false
        } else {
            // We are just now obtaining the lock
            *guard.lock_var_mut() = true;
            true
        }
    }

    #[inline]
    pub unsafe fn destroy(&self) {}
}

struct ReentrantLock {
    owner: Option<Tcs>,
    count: usize,
}

pub struct ReentrantMutex {
    inner: SpinMutex<WaitVariable<ReentrantLock>>,
}

impl ReentrantMutex {
    pub const fn uninitialized() -> ReentrantMutex {
        ReentrantMutex {
            inner: SpinMutex::new(WaitVariable::new(ReentrantLock { owner: None, count: 0 })),
        }
    }

    #[inline]
    pub unsafe fn init(&self) {}

    #[inline]
    pub unsafe fn lock(&self) {
        let mut guard = self.inner.lock();
        match guard.lock_var().owner {
            Some(tcs) if tcs != thread::current() => {
                // Another thread has the lock, wait
                WaitQueue::wait(guard, || {});
                // Another thread has passed the lock to us
            }
            _ => {
                // We are just now obtaining the lock
                guard.lock_var_mut().owner = Some(thread::current());
                guard.lock_var_mut().count += 1;
            }
        }
    }

    #[inline]
    pub unsafe fn unlock(&self) {
        let mut guard = self.inner.lock();
        if guard.lock_var().count > 1 {
            guard.lock_var_mut().count -= 1;
        } else {
            match WaitQueue::notify_one(guard) {
                Err(mut guard) => {
                    // No other waiters, unlock
                    guard.lock_var_mut().count = 0;
                    guard.lock_var_mut().owner = None;
                }
                Ok(mut guard) => {
                    // There was a thread waiting, just pass the lock
                    if let NotifiedTcs::Single(tcs) = guard.notified_tcs() {
                        guard.lock_var_mut().owner = Some(tcs)
                    } else {
                        unreachable!() // called notify_one
                    }
                }
            }
        }
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        let mut guard = try_lock_or_false!(self.inner);
        match guard.lock_var().owner {
            Some(tcs) if tcs != thread::current() => {
                // Another thread has the lock
                false
            }
            _ => {
                // We are just now obtaining the lock
                guard.lock_var_mut().owner = Some(thread::current());
                guard.lock_var_mut().count += 1;
                true
            }
        }
    }

    #[inline]
    pub unsafe fn destroy(&self) {}
}
<commit_msg>Rollup merge of #85029 - jethrogb:jb/sgx-movable-mutex, r=m-ou-se<commit_after>use fortanix_sgx_abi::Tcs;

use super::abi::thread;

use super::waitqueue::{try_lock_or_false, NotifiedTcs, SpinMutex, WaitQueue, WaitVariable};

pub struct Mutex {
    inner: SpinMutex<WaitVariable<bool>>,
}

pub type MovableMutex = Mutex;

// Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
impl Mutex {
    pub const fn new() -> Mutex {
        Mutex { inner: SpinMutex::new(WaitVariable::new(false)) }
    }

    #[inline]
    pub unsafe fn init(&mut self) {}

    #[inline]
    pub unsafe fn lock(&self) {
        let mut guard = self.inner.lock();
        if *guard.lock_var() {
            // Another thread has the lock, wait
            WaitQueue::wait(guard, || {})
        // Another thread has passed the lock to us
        } else {
            // We are just now obtaining the lock
            *guard.lock_var_mut() = true;
        }
    }

    #[inline]
    pub unsafe fn unlock(&self) {
        let guard = self.inner.lock();
        if let Err(mut guard) = WaitQueue::notify_one(guard) {
            // No other waiters, unlock
            *guard.lock_var_mut() = false;
        } else {
            // There was a thread waiting, just pass the lock
        }
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        let mut guard = try_lock_or_false!(self.inner);
        if *guard.lock_var() {
            // Another thread has the lock
            false
        } else {
            // We are just now obtaining the lock
            *guard.lock_var_mut() = true;
            true
        }
    }

    #[inline]
    pub unsafe fn destroy(&self) {}
}

struct ReentrantLock {
    owner: Option<Tcs>,
    count: usize,
}

pub struct ReentrantMutex {
    inner: SpinMutex<WaitVariable<ReentrantLock>>,
}

impl ReentrantMutex {
    pub const fn uninitialized() -> ReentrantMutex {
        ReentrantMutex {
            inner: SpinMutex::new(WaitVariable::new(ReentrantLock { owner: None, count: 0 })),
        }
    }

    #[inline]
    pub unsafe fn init(&self) {}

    #[inline]
    pub unsafe fn lock(&self) {
        let mut guard = self.inner.lock();
        match guard.lock_var().owner {
            Some(tcs) if tcs != thread::current() => {
                // Another thread has the lock, wait
                WaitQueue::wait(guard, || {});
                // Another thread has passed the lock to us
            }
            _ => {
                // We are just now obtaining the lock
                guard.lock_var_mut().owner = Some(thread::current());
                guard.lock_var_mut().count += 1;
            }
        }
    }

    #[inline]
    pub unsafe fn unlock(&self) {
        let mut guard = self.inner.lock();
        if guard.lock_var().count > 1 {
            guard.lock_var_mut().count -= 1;
        } else {
            match WaitQueue::notify_one(guard) {
                Err(mut guard) => {
                    // No other waiters, unlock
                    guard.lock_var_mut().count = 0;
                    guard.lock_var_mut().owner = None;
                }
                Ok(mut guard) => {
                    // There was a thread waiting, just pass the lock
                    if let NotifiedTcs::Single(tcs) = guard.notified_tcs() {
                        guard.lock_var_mut().owner = Some(tcs)
                    } else {
                        unreachable!() // called notify_one
                    }
                }
            }
        }
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        let mut guard = try_lock_or_false!(self.inner);
        match guard.lock_var().owner {
            Some(tcs) if tcs != thread::current() => {
                // Another thread has the lock
                false
            }
            _ => {
                // We are just now obtaining the lock
                guard.lock_var_mut().owner = Some(thread::current());
                guard.lock_var_mut().count += 1;
                true
            }
        }
    }

    #[inline]
    pub unsafe fn destroy(&self) {}
}
<|endoftext|>


<commit_before>#[derive(PartialEq, Eq, Debug)]
struct Age(u8);

struct Person<'a> {
    name: &'static str,
    parent: Option<&'a Person<'a>>,
}

impl<'a> Person<'a> {
    fn new(name: &'static str, parent: Option<&'a Person<'a>>) -> Person<'a> {
        Person{name: name, parent: parent}
    }

    fn parents_name(&self) -> Option<&'static str> {
        match self.parent {
            Some(p) => Some(p.name),
            None => None,
        }
    }
}

// This one can be elided.
fn first_five<'a>(value: &'a String) -> &'a str {
    &value[..5]
}

// This cannot be elided because Rust doesn't know to use lifetime of "a" or "b".
fn double_first_five<'a>(a: &'a String, b: &'a String) -> (&'a str, &'a str) {
    (&a[..5], &b[..5])
}

// Output borrows generally must have an input value from which it can borrow. The exception is
// the static lifetime.
// Couldn't Rust infer from the body of the function that the borrows are from the static lifetime?
//   - I feel that Rust favours explicitness over terseness. A functions behaviour should be
//   encoded directly into it's signature.
fn output_only<'a>() -> (&'static u8, &'static u8) {
    static X: u8 = 8;
    static Y: u8 = 9;

    (&X, &Y)
}

// Here we are promising Rust that all of the borrowed u8's
// live for the same scope.
// Q: Why do I need a lifetime here?
fn join_ages<'a, T: Iterator>(iters: T) -> Vec<&'a Age>
        where T::Item: IntoIterator<Item=&'a Age> {
    iters.flat_map(|b| b.into_iter())
         .collect()
}

// This is not really necessary here. Both a and b could use the same lifetime
// as Rust only cares that a and b are available for the scope of this function.
// This could also be elided.
fn multi_lifetimes<'a, 'b>(a: &'a u8, b: &'b u8) -> bool {
    (a + b) > 10
}

fn multiple_lifetimes() -> bool {
    let a = &9;

    {
        let b = &9;

        multi_lifetimes(a, b)
    }
}

#[test]
fn it_works() {
    let jane = Person::new("Jane", None);
    let tom = Person::new("Tom", Some(&jane));
    let name = "Andrew".to_owned();
    let another = "Timothy".to_owned();
    let a = 43;
    let vec_ages = vec![vec![Age(90), Age(80)],
                        vec![Age(2)]];

    // Error: This cannot work because the lifetime of the borrow (Rob) is only valid for
    // the expression on the right-hand side. We must increase it's lifetime by giving it a name
    // via 'let'.
    //let bob = Person::new("Bob", Some(&Person::new("Rob", None)));

    // If we swap these two lines around then this will not compile because the lifetime of Mary
    // would be less than that of Bob.
    let mary = Person::new("Mary", None);
    let mut bob = Person::new("Bob", None);

    bob.parent = Some(&mary);

    let arr_ages = vec![[Age(90), Age(80)],
                        [Age(2), Age(45)]];

    assert_eq!(output_only(), (&8, &9));

    assert_eq!(first_five(&name), "Andre");
    assert_eq!(double_first_five(&name, &another), ("Andre", "Timot"));

    assert!(multiple_lifetimes());

    assert_eq!(tom.name, "Tom");
    assert_eq!(jane.name, "Jane");
    assert_eq!(tom.parent.unwrap().name, "Jane");
    assert_eq!(tom.parents_name(), Some("Jane"));
    assert_eq!(jane.parents_name(), None);

    assert_eq!(join_ages(vec_ages.iter()), vec![&Age(90), &Age(80), &Age(2)]);
    assert_eq!(join_ages(arr_ages.iter()), vec![&Age(90), &Age(80), &Age(2), &Age(45)]);
}

// - We are making a promise to the compiler that all of these things live for atleast the same scope.
// - We are not asking the compiler to "create a lifetime". We are just telling it to complain if we
//   don't do what we say we are doing.
// - Nor are you telling Rust to "allow" a binding to be available in a given named scope/lifetime.
// - Why? Because this allows Rust to ensure we cannot cause common memory allocation bugs. It does
//   this at compile time. It's a zero-cost abstraction because there is no runtime penalty.
// - It makes code look "uglier". But this is the wrong mindset for writing systems-level programs.
//   The emphasis here is on safety, not expressiveness.
// - When we say "'a", we are talking about a scope in the calling environment.
// - Question: Why can't Rust ensure/infer/elide the struct scenario? Surely any reference to a Parent
//   must *always* live for the same or a bigger scope???
//   - There is an open RFC for this
//   - It may be complex to implement and/or slow down compilation
//   - Eliding in more cases may prevent newcomer Rust programmers from ever encountering
//     lifetimes, which could have a negative impact in the long run. Pedagogy!
<commit_msg>Added note explaining why order of lets is important<commit_after>#[derive(PartialEq, Eq, Debug)]
struct Age(u8);

struct Person<'a> {
    name: &'static str,
    parent: Option<&'a Person<'a>>,
}

impl<'a> Person<'a> {
    fn new(name: &'static str, parent: Option<&'a Person<'a>>) -> Person<'a> {
        Person{name: name, parent: parent}
    }

    fn parents_name(&self) -> Option<&'static str> {
        match self.parent {
            Some(p) => Some(p.name),
            None => None,
        }
    }
}

// This one can be elided.
fn first_five<'a>(value: &'a String) -> &'a str {
    &value[..5]
}

// This cannot be elided because Rust doesn't know to use lifetime of "a" or "b".
fn double_first_five<'a>(a: &'a String, b: &'a String) -> (&'a str, &'a str) {
    (&a[..5], &b[..5])
}

// Output borrows generally must have an input value from which it can borrow. The exception is
// the static lifetime.
// Couldn't Rust infer from the body of the function that the borrows are from the static lifetime?
//   - I feel that Rust favours explicitness over terseness. A functions behaviour should be
//   encoded directly into it's signature.
fn output_only<'a>() -> (&'static u8, &'static u8) {
    static X: u8 = 8;
    static Y: u8 = 9;

    (&X, &Y)
}

// Here we are promising Rust that all of the borrowed u8's
// live for the same scope.
// Q: Why do I need a lifetime here?
fn join_ages<'a, T: Iterator>(iters: T) -> Vec<&'a Age>
        where T::Item: IntoIterator<Item=&'a Age> {
    iters.flat_map(|b| b.into_iter())
         .collect()
}

// This is not really necessary here. Both a and b could use the same lifetime
// as Rust only cares that a and b are available for the scope of this function.
// This could also be elided.
fn multi_lifetimes<'a, 'b>(a: &'a u8, b: &'b u8) -> bool {
    (a + b) > 10
}

fn multiple_lifetimes() -> bool {
    let a = &9;

    {
        let b = &9;

        multi_lifetimes(a, b)
    }
}

#[test]
fn it_works() {
    let jane = Person::new("Jane", None);
    let tom = Person::new("Tom", Some(&jane));
    let name = "Andrew".to_owned();
    let another = "Timothy".to_owned();
    let a = 43;
    let vec_ages = vec![vec![Age(90), Age(80)],
                        vec![Age(2)]];

    // Error: This cannot work because the lifetime of the borrow (Rob) is only valid for
    // the expression on the right-hand side. We must increase it's lifetime by giving it a name
    // via 'let'.
    //let bob = Person::new("Bob", Some(&Person::new("Rob", None)));

    // If we swap these two lines around then this will not compile because the lifetime of Mary
    // would be less than that of Bob. The definition of the "new" method above states that both
    // Person and their optional parent (&Person) must have the same lifetime). This is kind of
    // unfortunate because, as Humans, we know that this code is safe, but Rust is being strict on
    // us in this situation because when many and bob are deallocated at the end of their scope,
    // there will be a brief instant where bob is borrowing mary even though she's been
    // deallocated.
    let mary = Person::new("Mary", None);
    let mut bob = Person::new("Bob", None);

    bob.parent = Some(&mary);

    let arr_ages = vec![[Age(90), Age(80)],
                        [Age(2), Age(45)]];

    assert_eq!(output_only(), (&8, &9));

    assert_eq!(first_five(&name), "Andre");
    assert_eq!(double_first_five(&name, &another), ("Andre", "Timot"));

    assert!(multiple_lifetimes());

    assert_eq!(tom.name, "Tom");
    assert_eq!(jane.name, "Jane");
    assert_eq!(tom.parent.unwrap().name, "Jane");
    assert_eq!(tom.parents_name(), Some("Jane"));
    assert_eq!(jane.parents_name(), None);

    assert_eq!(join_ages(vec_ages.iter()), vec![&Age(90), &Age(80), &Age(2)]);
    assert_eq!(join_ages(arr_ages.iter()), vec![&Age(90), &Age(80), &Age(2), &Age(45)]);
}

// - We are making a promise to the compiler that all of these things live for atleast the same scope.
// - We are not asking the compiler to "create a lifetime". We are just telling it to complain if we
//   don't do what we say we are doing.
// - Nor are you telling Rust to "allow" a binding to be available in a given named scope/lifetime.
// - Why? Because this allows Rust to ensure we cannot cause common memory allocation bugs. It does
//   this at compile time. It's a zero-cost abstraction because there is no runtime penalty.
// - It makes code look "uglier". But this is the wrong mindset for writing systems-level programs.
//   The emphasis here is on safety, not expressiveness.
// - When we say "'a", we are talking about a scope in the calling environment.
// - Question: Why can't Rust ensure/infer/elide the struct scenario? Surely any reference to a Parent
//   must *always* live for the same or a bigger scope???
//   - There is an open RFC for this
//   - It may be complex to implement and/or slow down compilation
//   - Eliding in more cases may prevent newcomer Rust programmers from ever encountering
//     lifetimes, which could have a negative impact in the long run. Pedagogy!
<|endoftext|>


<commit_before>// Copyright 2017 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Tests for async mode.. should be run with RUST_TEST_THREADS=1

extern crate cuckoo_miner as cuckoo;
extern crate time;

mod common;
use common::{SAMPLE_GRIN_PRE_HEADER_1, SAMPLE_GRIN_POST_HEADER_1};

use cuckoo::{CuckooMinerConfig, CuckooMiner};

// Helper function, tests a particular miner implementation against a known set
fn mine_async_for_duration(full_paths: Vec<&str>, duration_in_seconds: i64) {
	let mut config_vec=Vec::new();
	for p in full_paths.into_iter() {
		let mut config = CuckooMinerConfig::new();
		config.plugin_full_path = String::from(p);
		config_vec.push(config);
	}

	let stat_check_interval = 3;
	let deadline = time::get_time().sec + duration_in_seconds;
	let mut next_stat_check = time::get_time().sec + stat_check_interval;
	let mut stats_updated=false;

	while time::get_time().sec < deadline {

		println!("Test mining for {} seconds, looking for difficulty > 0", duration_in_seconds);
		let mut i=0;
		for c in config_vec.clone().into_iter(){
			println!("Plugin {}: {}", i, c.plugin_full_path);
			i+=1;
		}

		// these always get consumed after a notify
		let miner = CuckooMiner::new(config_vec.clone()).expect("");
		let job_handle = miner.notify(1, SAMPLE_GRIN_PRE_HEADER_1, SAMPLE_GRIN_POST_HEADER_1, 0).unwrap();

		loop {
			if let Some(s) = job_handle.get_solution() {
				println!("Sol found: {}, {:?}", s.get_nonce_as_u64(), s);
				// up to you to read it and check difficulty
				continue;
			}
			if time::get_time().sec >= next_stat_check {
				let mut sps_total=0.0;
				for index in 0..config_vec.len() {
					let stats_vec=job_handle.get_stats(index);
					if let Err(e) = stats_vec {
						panic!("Error getting stats: {:?}", e);
					}
					for s in stats_vec.unwrap().into_iter() {
						let last_solution_time_secs = s.last_solution_time as f64 / 1000.0;
						let last_hashes_per_sec = 1.0 / last_solution_time_secs;
						println!("Plugin {} - Device {} ({}) - Last Solution time: {}; Solutions per second: {:.*}",
						index,s.device_id, s.device_name, last_solution_time_secs, 3, last_hashes_per_sec);
						if last_hashes_per_sec.is_finite() {
							sps_total+=last_hashes_per_sec;
						}
						if last_solution_time_secs > 0.0 {
							stats_updated = true;
						}
						i+=1;
					}
				}
				println!("Total solutions per second: {}", sps_total);
				next_stat_check = time::get_time().sec + stat_check_interval;
			}
			if time::get_time().sec > deadline {
				println!("Stopping jobs and waiting for cleanup");
				job_handle.stop_jobs();
				break;
			}
		}
	}
	assert!(stats_updated==true);
}

//mines for a bit on each available plugin, one after the other
#[test]
fn on_commit_mine_single_plugin_async() {
	let caps = common::get_plugin_vec("");
	for c in &caps {
	 let mut plugin_path_vec:Vec<&str> = Vec::new();
		plugin_path_vec.push(&c.full_path);
		mine_async_for_duration(plugin_path_vec, 180);
	}
}

//Same as above, but only for cuda
#[test]
fn on_cuda_commit_mine_single_plugin_async() {
	let caps = common::get_plugin_vec("cuda");
	for c in &caps {
	 let mut plugin_path_vec:Vec<&str> = Vec::new();
		plugin_path_vec.push(&c.full_path);
		mine_async_for_duration(plugin_path_vec, 180);
	}
}

//Mines for a bit on all available plugins at once
//(won't be efficient, but should stress-tes plugins nicely)
#[test]
fn on_commit_mine_all_plugins_async() {
	// Get a list of installed plugins and capabilities
	// only do cuckoo 30s
	let caps = common::get_plugin_vec("30");
	let mut plugin_path_vec:Vec<&str> = Vec::new();
	for c in &caps {
		plugin_path_vec.push(&c.full_path);
	}
	mine_async_for_duration(plugin_path_vec, 120);
}
<commit_msg>allowing extra solution time for really slow travis CI server<commit_after>// Copyright 2017 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Tests for async mode.. should be run with RUST_TEST_THREADS=1

extern crate cuckoo_miner as cuckoo;
extern crate time;

mod common;
use common::{SAMPLE_GRIN_PRE_HEADER_1, SAMPLE_GRIN_POST_HEADER_1};

use cuckoo::{CuckooMinerConfig, CuckooMiner};

// Helper function, tests a particular miner implementation against a known set
fn mine_async_for_duration(full_paths: Vec<&str>, duration_in_seconds: i64) {
	let mut config_vec=Vec::new();
	for p in full_paths.into_iter() {
		let mut config = CuckooMinerConfig::new();
		config.plugin_full_path = String::from(p);
		config_vec.push(config);
	}

	let stat_check_interval = 3;
	let mut deadline = time::get_time().sec + duration_in_seconds;
	let mut next_stat_check = time::get_time().sec + stat_check_interval;
	let mut stats_updated=false;
	//for CI testing on slower servers
	//if we're trying to quit and there are no stats yet, keep going for a bit
	let mut extra_time=false;
	let extra_time_value=180;

	while time::get_time().sec < deadline {

		println!("Test mining for {} seconds, looking for difficulty > 0", duration_in_seconds);
		let mut i=0;
		for c in config_vec.clone().into_iter(){
			println!("Plugin {}: {}", i, c.plugin_full_path);
			i+=1;
		}

		// these always get consumed after a notify
		let miner = CuckooMiner::new(config_vec.clone()).expect("");
		let job_handle = miner.notify(1, SAMPLE_GRIN_PRE_HEADER_1, SAMPLE_GRIN_POST_HEADER_1, 0).unwrap();

		loop {
			if let Some(s) = job_handle.get_solution() {
				println!("Sol found: {}, {:?}", s.get_nonce_as_u64(), s);
				// up to you to read it and check difficulty
				continue;
			}
			if time::get_time().sec >= next_stat_check {
				let mut sps_total=0.0;
				for index in 0..config_vec.len() {
					let stats_vec=job_handle.get_stats(index);
					if let Err(e) = stats_vec {
						panic!("Error getting stats: {:?}", e);
					}
					for s in stats_vec.unwrap().into_iter() {
						let last_solution_time_secs = s.last_solution_time as f64 / 1000.0;
						let last_hashes_per_sec = 1.0 / last_solution_time_secs;
						println!("Plugin {} - Device {} ({}) - Last Solution time: {}; Solutions per second: {:.*}",
						index,s.device_id, s.device_name, last_solution_time_secs, 3, last_hashes_per_sec);
						if last_hashes_per_sec.is_finite() {
							sps_total+=last_hashes_per_sec;
						}
						if last_solution_time_secs > 0.0 {
							stats_updated = true;
							if extra_time {
								break;
							}
						}
						i+=1;
					}
				}
				println!("Total solutions per second: {}", sps_total);
				next_stat_check = time::get_time().sec + stat_check_interval;
			}
			if time::get_time().sec > deadline {
				if !stats_updated && !extra_time {
					extra_time=true;
					deadline+=extra_time_value;
				}
				println!("Stopping jobs and waiting for cleanup");
				job_handle.stop_jobs();
				break;
			}
		}
	}
	assert!(stats_updated==true);
}

//mines for a bit on each available plugin, one after the other
#[test]
fn on_commit_mine_single_plugin_async() {
	let caps = common::get_plugin_vec("");
	for c in &caps {
	 let mut plugin_path_vec:Vec<&str> = Vec::new();
		plugin_path_vec.push(&c.full_path);
		mine_async_for_duration(plugin_path_vec, 180);
	}
}

//Same as above, but only for cuda
#[test]
fn on_cuda_commit_mine_single_plugin_async() {
	let caps = common::get_plugin_vec("cuda");
	for c in &caps {
	 let mut plugin_path_vec:Vec<&str> = Vec::new();
		plugin_path_vec.push(&c.full_path);
		mine_async_for_duration(plugin_path_vec, 180);
	}
}

//Mines for a bit on all available plugins at once
//(won't be efficient, but should stress-tes plugins nicely)
#[test]
fn on_commit_mine_all_plugins_async() {
	// Get a list of installed plugins and capabilities
	// only do cuckoo 30s
	let caps = common::get_plugin_vec("30");
	let mut plugin_path_vec:Vec<&str> = Vec::new();
	for c in &caps {
		plugin_path_vec.push(&c.full_path);
	}
	mine_async_for_duration(plugin_path_vec, 120);
}
<|endoftext|>


<commit_before>extern crate tiny_http;

use std::io::{copy, Read, Write};
use std::net::{Shutdown, TcpStream};
use std::ops::Deref;
use std::sync::mpsc::channel;
use std::sync::Arc;
use std::thread::{sleep, spawn};
use std::time::Duration;
use tiny_http::{Response, Server};

/// Stream that produces bytes very slowly
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
struct SlowByteSrc {
    val: u8,
    len: usize,
}
impl<'b> Read for SlowByteSrc {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        sleep(Duration::from_millis(100));
        let l = self.len.min(buf.len()).min(1000);
        buf[..l].fill(self.val);
        self.len -= l;
        Ok(l)
    }
}

/// crude impl of http `Transfer-Encoding: chunked`
fn encode_chunked(data: &mut dyn Read, output: &mut dyn Write) {
    let mut buf = [0u8; 4096];
    loop {
        let l = data.read(&mut buf).unwrap();
        write!(output, "{:X}\r\n", l).unwrap();
        output.write_all(&buf[..l]).unwrap();
        write!(output, "\r\n").unwrap();
        if l == 0 {
            break;
        }
    }
}

mod prompt_pipelining {
    use super::*;

    /// Check that pipelined requests on the same connection are received promptly.
    fn assert_requests_parsed_promptly(
        req_cnt: usize,
        req_body: &'static [u8],
        timeout: Duration,
        req_writer: impl FnOnce(&mut dyn Write) + Send + 'static,
    ) {
        let resp_body = SlowByteSrc {
            val: 42,
            len: 1000_000,
        }; // very slow response body

        let server = Server::http("0.0.0.0:0").unwrap();
        let mut client = TcpStream::connect(server.server_addr()).unwrap();
        let (svr_send, svr_rcv) = channel();

        spawn(move || {
            for _ in 0..req_cnt {
                let mut req = server.recv().unwrap();
                // read the whole body of the request
                let mut body = Vec::new();
                req.as_reader().read_to_end(&mut body).unwrap();
                assert_eq!(req_body, body.as_slice());
                // The next pipelined request should now be available for parsing,
                // while we send the (possibly slow) response in another thread
                spawn(move || {
                    req.respond(Response::empty(200).with_data(resp_body, Some(resp_body.len)))
                });
            }
            svr_send.send(()).unwrap();
        });

        spawn(move || req_writer(&mut client));

        // requests must be sent and received quickly (before timeout expires)
        svr_rcv
            .recv_timeout(timeout)
            .expect("Server did not finish reading pipelined requests quickly enough");
    }

    #[test]
    fn empty() {
        assert_requests_parsed_promptly(5, &[], Duration::from_millis(200), move |wr| {
            for _ in 0..5 {
                write!(wr, "GET / HTTP/1.1\r\n").unwrap();
                write!(wr, "Connection: keep-alive\r\n\r\n").unwrap();
            }
        });
    }

    #[test]
    fn content_length_short() {
        let body = &[65u8; 100]; // short but not trivial
        assert_requests_parsed_promptly(5, body, Duration::from_millis(200), move |wr| {
            for _ in 0..5 {
                write!(wr, "GET / HTTP/1.1\r\n").unwrap();
                write!(wr, "Connection: keep-alive\r\n").unwrap();
                write!(wr, "Content-Length: {}\r\n\r\n", body.len()).unwrap();
                wr.write_all(body).unwrap();
            }
        });
    }

    #[test]
    fn content_length_long() {
        let body = &[65u8; 10000]; // long enough that it won't be buffered
        assert_requests_parsed_promptly(5, body, Duration::from_millis(200), move |wr| {
            for _ in 0..5 {
                write!(wr, "GET / HTTP/1.1\r\n").unwrap();
                write!(wr, "Connection: keep-alive\r\n").unwrap();
                write!(wr, "Content-Length: {}\r\n\r\n", body.len()).unwrap();
                wr.write_all(body).unwrap();
            }
        });
    }

    #[test]
    fn chunked() {
        let body = &[65u8; 10000];
        assert_requests_parsed_promptly(5, body, Duration::from_millis(200), move |wr| {
            for _ in 0..5 {
                write!(wr, "GET / HTTP/1.1\r\n").unwrap();
                write!(wr, "Connection: keep-alive\r\n").unwrap();
                write!(wr, "Transfer-Encoding: chunked\r\n\r\n").unwrap();
                encode_chunked(&mut &body[..], wr);
            }
        });
    }
}

mod prompt_responses {
    use super::*;

    /// Check that response is sent promptly without waiting for full request body.
    fn assert_responds_promptly(
        timeout: Duration,
        req_writer: impl FnOnce(&mut dyn Write) + Send + 'static,
    ) {
        let server = Server::http("0.0.0.0:0").unwrap();
        let client = TcpStream::connect(server.server_addr()).unwrap();

        spawn(move || loop {
            // server attempts to respond immediately
            let req = server.recv().unwrap();
            req.respond(Response::empty(400)).unwrap();
        });

        let client = Arc::new(client);
        let client_write = Arc::clone(&client);
        // request written (possibly very slowly) in another thread
        spawn(move || req_writer(&mut client_write.deref()));

        // response should arrive quickly (before timeout expires)
        client.set_read_timeout(Some(timeout)).unwrap();
        let resp = client.deref().read(&mut [0u8; 4096]);
        client.shutdown(Shutdown::Both).unwrap();
        assert!(resp.is_ok(), "Server response was not sent promptly");
    }

    static SLOW_BODY: SlowByteSrc = SlowByteSrc {
        val: 65,
        len: 1000_000,
    };

    #[test]
    fn content_length_http11() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.1\r\n").unwrap();
            write!(wr, "Content-Length: {}\r\n\r\n", SLOW_BODY.len).unwrap();
            copy(&mut SLOW_BODY.clone(), wr).unwrap();
        });
    }

    #[test]
    fn content_length_http10() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.0\r\n").unwrap();
            write!(wr, "Content-Length: {}\r\n\r\n", SLOW_BODY.len).unwrap();
            copy(&mut SLOW_BODY.clone(), wr).unwrap();
        });
    }

    #[test]
    fn expect_continue() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.1\r\n").unwrap();
            write!(wr, "Expect: 100 continue\r\n").unwrap();
            write!(wr, "Content-Length: {}\r\n\r\n", SLOW_BODY.len).unwrap();
            copy(&mut SLOW_BODY.clone(), wr).unwrap();
        });
    }

    #[test]
    fn chunked() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.1\r\n").unwrap();
            write!(wr, "Transfer-Encoding: chunked\r\n\r\n").unwrap();
            encode_chunked(&mut SLOW_BODY.clone(), wr);
        });
    }
}
<commit_msg>Replace `slice::fill` with an explicit loop for Rust 1.41 compat<commit_after>extern crate tiny_http;

use std::io::{copy, Read, Write};
use std::net::{Shutdown, TcpStream};
use std::ops::Deref;
use std::sync::mpsc::channel;
use std::sync::Arc;
use std::thread::{sleep, spawn};
use std::time::Duration;
use tiny_http::{Response, Server};

/// Stream that produces bytes very slowly
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
struct SlowByteSrc {
    val: u8,
    len: usize,
}
impl<'b> Read for SlowByteSrc {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        sleep(Duration::from_millis(100));
        let l = self.len.min(buf.len()).min(1000);
        for v in buf[..l].iter_mut() {
            *v = self.val;
        }
        self.len -= l;
        Ok(l)
    }
}

/// crude impl of http `Transfer-Encoding: chunked`
fn encode_chunked(data: &mut dyn Read, output: &mut dyn Write) {
    let mut buf = [0u8; 4096];
    loop {
        let l = data.read(&mut buf).unwrap();
        write!(output, "{:X}\r\n", l).unwrap();
        output.write_all(&buf[..l]).unwrap();
        write!(output, "\r\n").unwrap();
        if l == 0 {
            break;
        }
    }
}

mod prompt_pipelining {
    use super::*;

    /// Check that pipelined requests on the same connection are received promptly.
    fn assert_requests_parsed_promptly(
        req_cnt: usize,
        req_body: &'static [u8],
        timeout: Duration,
        req_writer: impl FnOnce(&mut dyn Write) + Send + 'static,
    ) {
        let resp_body = SlowByteSrc {
            val: 42,
            len: 1000_000,
        }; // very slow response body

        let server = Server::http("0.0.0.0:0").unwrap();
        let mut client = TcpStream::connect(server.server_addr()).unwrap();
        let (svr_send, svr_rcv) = channel();

        spawn(move || {
            for _ in 0..req_cnt {
                let mut req = server.recv().unwrap();
                // read the whole body of the request
                let mut body = Vec::new();
                req.as_reader().read_to_end(&mut body).unwrap();
                assert_eq!(req_body, body.as_slice());
                // The next pipelined request should now be available for parsing,
                // while we send the (possibly slow) response in another thread
                spawn(move || {
                    req.respond(Response::empty(200).with_data(resp_body, Some(resp_body.len)))
                });
            }
            svr_send.send(()).unwrap();
        });

        spawn(move || req_writer(&mut client));

        // requests must be sent and received quickly (before timeout expires)
        svr_rcv
            .recv_timeout(timeout)
            .expect("Server did not finish reading pipelined requests quickly enough");
    }

    #[test]
    fn empty() {
        assert_requests_parsed_promptly(5, &[], Duration::from_millis(200), move |wr| {
            for _ in 0..5 {
                write!(wr, "GET / HTTP/1.1\r\n").unwrap();
                write!(wr, "Connection: keep-alive\r\n\r\n").unwrap();
            }
        });
    }

    #[test]
    fn content_length_short() {
        let body = &[65u8; 100]; // short but not trivial
        assert_requests_parsed_promptly(5, body, Duration::from_millis(200), move |wr| {
            for _ in 0..5 {
                write!(wr, "GET / HTTP/1.1\r\n").unwrap();
                write!(wr, "Connection: keep-alive\r\n").unwrap();
                write!(wr, "Content-Length: {}\r\n\r\n", body.len()).unwrap();
                wr.write_all(body).unwrap();
            }
        });
    }

    #[test]
    fn content_length_long() {
        let body = &[65u8; 10000]; // long enough that it won't be buffered
        assert_requests_parsed_promptly(5, body, Duration::from_millis(200), move |wr| {
            for _ in 0..5 {
                write!(wr, "GET / HTTP/1.1\r\n").unwrap();
                write!(wr, "Connection: keep-alive\r\n").unwrap();
                write!(wr, "Content-Length: {}\r\n\r\n", body.len()).unwrap();
                wr.write_all(body).unwrap();
            }
        });
    }

    #[test]
    fn chunked() {
        let body = &[65u8; 10000];
        assert_requests_parsed_promptly(5, body, Duration::from_millis(200), move |wr| {
            for _ in 0..5 {
                write!(wr, "GET / HTTP/1.1\r\n").unwrap();
                write!(wr, "Connection: keep-alive\r\n").unwrap();
                write!(wr, "Transfer-Encoding: chunked\r\n\r\n").unwrap();
                encode_chunked(&mut &body[..], wr);
            }
        });
    }
}

mod prompt_responses {
    use super::*;

    /// Check that response is sent promptly without waiting for full request body.
    fn assert_responds_promptly(
        timeout: Duration,
        req_writer: impl FnOnce(&mut dyn Write) + Send + 'static,
    ) {
        let server = Server::http("0.0.0.0:0").unwrap();
        let client = TcpStream::connect(server.server_addr()).unwrap();

        spawn(move || loop {
            // server attempts to respond immediately
            let req = server.recv().unwrap();
            req.respond(Response::empty(400)).unwrap();
        });

        let client = Arc::new(client);
        let client_write = Arc::clone(&client);
        // request written (possibly very slowly) in another thread
        spawn(move || req_writer(&mut client_write.deref()));

        // response should arrive quickly (before timeout expires)
        client.set_read_timeout(Some(timeout)).unwrap();
        let resp = client.deref().read(&mut [0u8; 4096]);
        client.shutdown(Shutdown::Both).unwrap();
        assert!(resp.is_ok(), "Server response was not sent promptly");
    }

    static SLOW_BODY: SlowByteSrc = SlowByteSrc {
        val: 65,
        len: 1000_000,
    };

    #[test]
    fn content_length_http11() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.1\r\n").unwrap();
            write!(wr, "Content-Length: {}\r\n\r\n", SLOW_BODY.len).unwrap();
            copy(&mut SLOW_BODY.clone(), wr).unwrap();
        });
    }

    #[test]
    fn content_length_http10() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.0\r\n").unwrap();
            write!(wr, "Content-Length: {}\r\n\r\n", SLOW_BODY.len).unwrap();
            copy(&mut SLOW_BODY.clone(), wr).unwrap();
        });
    }

    #[test]
    fn expect_continue() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.1\r\n").unwrap();
            write!(wr, "Expect: 100 continue\r\n").unwrap();
            write!(wr, "Content-Length: {}\r\n\r\n", SLOW_BODY.len).unwrap();
            copy(&mut SLOW_BODY.clone(), wr).unwrap();
        });
    }

    #[test]
    fn chunked() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.1\r\n").unwrap();
            write!(wr, "Transfer-Encoding: chunked\r\n\r\n").unwrap();
            encode_chunked(&mut SLOW_BODY.clone(), wr);
        });
    }
}
<|endoftext|>


<commit_before>use support::{ResultTest,Tap,shell_writes};
use hamcrest::{assert_that};
use std::io::{MemWriter, BufWriter, IoResult};
use std::str::from_utf8_lossy;
use cargo::core::shell::{Shell,ShellConfig};
use term::{Terminal,TerminfoTerminal,color};

fn setup() {
}

fn writer(buf: &mut [u8]) -> Box<Writer> {
    box BufWriter::new(buf) as Box<Writer>
}

test!(non_tty {
    let config = ShellConfig { color: true, verbose: true, tty: false };
    let mut buf: Vec<u8> = Vec::from_elem(9, 0 as u8);

    Shell::create(writer(buf.as_mut_slice()), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).assert();
        assert_that(buf.as_slice(), shell_writes("Hey Alex\n"));
    });
})

test!(color_explicitly_disabled {
    let config = ShellConfig { color: false, verbose: true, tty: true };
    let mut buf: Vec<u8> = Vec::from_elem(9, 0 as u8);

    Shell::create(writer(buf.as_mut_slice()), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).assert();
        assert_that(buf.as_slice(), shell_writes("Hey Alex\n"));
    });
})

test!(colored_shell {
    let config = ShellConfig { color: true, verbose: true, tty: true };
    let mut buf: Vec<u8> = Vec::from_elem(100, 0 as u8);

    Shell::create(writer(buf.as_mut_slice()), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).assert();
        let buf = buf.as_slice().slice_to(buf.iter().position(|a| *a == 0).unwrap());
        assert_that(buf, shell_writes(colored_output("Hey Alex\n",
                                                     color::RED).assert()));
    });
})

fn colored_output<S: Str>(string: S, color: color::Color) -> IoResult<String> {
    let mut term: TerminfoTerminal<MemWriter> =
        Terminal::new(MemWriter::new()).assert();
    try!(term.reset());
    try!(term.fg(color));
    try!(term.write_str(string.as_slice()));
    try!(term.reset());
    try!(term.flush());
    Ok(from_utf8_lossy(term.get_ref().get_ref()).to_str())
}
<commit_msg>Disable terminal tests on windows<commit_after>#![cfg(not(windows))] // getting the actual colored output is a little different
                      // on windows, so it's tough to get a reference copy of all
                      // the color

use support::{ResultTest,Tap,shell_writes};
use hamcrest::{assert_that};
use std::io::{MemWriter, BufWriter, IoResult};
use std::str::from_utf8_lossy;
use cargo::core::shell::{Shell,ShellConfig};
use term::{Terminal,TerminfoTerminal,color};

fn setup() {
}

fn writer(buf: &mut [u8]) -> Box<Writer> {
    box BufWriter::new(buf) as Box<Writer>
}

test!(non_tty {
    let config = ShellConfig { color: true, verbose: true, tty: false };
    let mut buf: Vec<u8> = Vec::from_elem(9, 0 as u8);

    Shell::create(writer(buf.as_mut_slice()), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).assert();
        assert_that(buf.as_slice(), shell_writes("Hey Alex\n"));
    });
})

test!(color_explicitly_disabled {
    let config = ShellConfig { color: false, verbose: true, tty: true };
    let mut buf: Vec<u8> = Vec::from_elem(9, 0 as u8);

    Shell::create(writer(buf.as_mut_slice()), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).assert();
        assert_that(buf.as_slice(), shell_writes("Hey Alex\n"));
    });
})

test!(colored_shell {
    let config = ShellConfig { color: true, verbose: true, tty: true };
    let mut buf: Vec<u8> = Vec::from_elem(100, 0 as u8);

    Shell::create(writer(buf.as_mut_slice()), config).tap(|shell| {
        shell.say("Hey Alex", color::RED).assert();
        let buf = buf.as_slice().slice_to(buf.iter().position(|a| *a == 0).unwrap());
        assert_that(buf, shell_writes(colored_output("Hey Alex\n",
                                                     color::RED).assert()));
    });
})

fn colored_output<S: Str>(string: S, color: color::Color) -> IoResult<String> {
    let mut term: TerminfoTerminal<MemWriter> =
        Terminal::new(MemWriter::new()).assert();
    try!(term.reset());
    try!(term.fg(color));
    try!(term.write_str(string.as_slice()));
    try!(term.reset());
    try!(term.flush());
    Ok(from_utf8_lossy(term.get_ref().get_ref()).to_str())
}
<|endoftext|>