<commit_before>extern crate crossbeam;
extern crate docopt;
extern crate image;
extern crate num;
extern crate num_cpus;
//extern crate serde;
//#[macro_use]
//extern crate serde_derive;

use image::ColorType;
use image::png::PNGEncoder;
use num::Complex;
use std::fs::File;
use std::io::Write;
use std::str::FromStr;

/*
const USAGE: &'static str = "\
mandelbrot.

Usage:
    mandelbrot <filename> <width> <height> <ulr> <uli> <lrr> <lri>
";

#[derive(Debug, Deserialize)]
struct Args {
    pub arg_filename: String,
    pub arg_width: usize,
    pub arg_height: usize,
    // TODO: figure out how deserialize works with Complex
    pub arg_ulr: f64,
    pub arg_uli: f64,
    pub arg_lrr: f64,
    pub arg_lri: f64,
}
*/

/// this is a documentation comment
fn escape_time(c: Complex<f64>, limit: u32) -> Option<u32> {
    let mut z = Complex::new(0.0, 0.0);
    for i in 0..limit {
        z = z * z + c;
        if z.norm_sqr() > 4.0 {
            return Some(i);
        }
    }
    None
}

fn pixel_to_point(
    bounds: (usize, usize),
    pixel: (usize, usize),
    upper_left: Complex<f64>,
    lower_right: Complex<f64>
) -> Complex<f64>
{
    let (width, height) = (lower_right.re - upper_left.re, upper_left.im - lower_right.im);
    Complex::new(
        upper_left.re + pixel.0 as f64 * width / bounds.0 as f64,
        upper_left.im - pixel.1 as f64 * height / bounds.1 as f64)
}

fn parse_pair<T: FromStr>(s: &str, separator: char) -> Option<(T, T)> {
    match s.find(separator) {
        None => None,
        Some(index) => {
            match (T::from_str(&s[..index]), T::from_str(&s[index + 1..])) {
                (Ok(l), Ok(r)) => Some((l, r)),
                _ => None,
            }
        }
    }
}

fn parse_complex(s: &str) -> Option<Complex<f64>> {
    match parse_pair(s, ',') {
        Some((re, im)) => Some(Complex::new(re, im)),
        None => None,
    }
}

fn render(pixels: &mut [u8], bounds: (usize, usize), upper_left: Complex<f64>, lower_right: Complex<f64>) {
    assert!(pixels.len() == bounds.0 * bounds.1);
    for row in 0..bounds.1 {
        for column in 0..bounds.0 {
            let point = pixel_to_point(bounds, (column, row), upper_left, lower_right);
            pixels[row * bounds.0 + column] = match escape_time(point, 255) {
                None => 0,
                Some(count) => 255 - count as u8
            };
        }
    }
}

fn write_image(filename: &str, pixels: &[u8], bounds: (usize, usize)) -> std::io::Result<()> {
    let output = File::create(filename)?;
    let encoder = PNGEncoder::new(output);
    encoder.encode(&pixels, bounds.0 as u32, bounds.1 as u32, ColorType::Gray(8))?;
    Ok(())
}

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

    let (width, height) = (args.arg_width, args.arg_height);
    let bounds = (width, height);
    let upper_left = Complex::new(args.arg_ulr, args.arg_uli);
    let lower_right = Complex::new(args.arg_lrr, args.arg_lri);
    */
    let args: Vec<String> = std::env::args().collect();
    if args.len() != 5 {
        writeln!(std::io::stderr(), "wrong number of args mofuck!").unwrap();
        std::process::exit(1);
    }
    let bounds = parse_pair(&args[2], 'x').expect("image dim fucked");
    let upper_left = parse_complex(&args[3]).expect("upper left fucked");
    let lower_right = parse_complex(&args[4]).expect("lower right fucked");
    let (width, height) = bounds;
    let mut pixels = vec![0; width * height];

    let threads = dbg!(num_cpus::get());
    let rows_per_band = height / threads + 1;
    {
        let bands: Vec<&mut [u8]> = pixels.chunks_mut(rows_per_band * width).collect();
        // blocks until all spawned threads finish
        crossbeam::scope(|spawner| {
            // into_iter gives each iteration exclusive ownership of one band
            for (i, band) in bands.into_iter().enumerate() {
                let top = rows_per_band * i;
                let end = band.len() / width;
                let band_bounds = (width, end);
                let band_upper_left = pixel_to_point(bounds, (0, top), upper_left, lower_right);
                let band_lower_right = pixel_to_point(bounds, (width, top + end), upper_left, lower_right);
                // move makes closure takes ownership of all variables it uses
                // only the closure may use mutable slice band
                spawner.spawn(move |_| {
                    render(band, band_bounds, band_upper_left, band_lower_right);
                });
            }
        }).unwrap();
    }
    write_image(&args[1], &pixels, bounds).expect("error writing PNG file");
}
<commit_msg>not working color<commit_after>extern crate crossbeam;
extern crate docopt;
extern crate image;
extern crate num;
extern crate num_cpus;
//extern crate serde;
//#[macro_use]
//extern crate serde_derive;

use image::ColorType;
use image::png::PNGEncoder;
use num::Complex;
use std::fs::File;
use std::io::Write;
use std::str::FromStr;

/*
const USAGE: &'static str = "\
mandelbrot.

Usage:
    mandelbrot <filename> <width> <height> <ulr> <uli> <lrr> <lri>
";

#[derive(Debug, Deserialize)]
struct Args {
    pub arg_filename: String,
    pub arg_width: usize,
    pub arg_height: usize,
    // TODO: figure out how deserialize works with Complex
    pub arg_ulr: f64,
    pub arg_uli: f64,
    pub arg_lrr: f64,
    pub arg_lri: f64,
}
*/

/// this is a documentation comment
fn escape_time(c: Complex<f64>, limit: u32) -> Option<u32> {
    let mut z = Complex::new(0.0, 0.0);
    for i in 0..limit {
        z = z * z + c;
        if z.norm_sqr() > 4.0 {
            return Some(i);
        }
    }
    None
}

fn pixel_to_point(
    bounds: (usize, usize),
    pixel: (usize, usize),
    upper_left: Complex<f64>,
    lower_right: Complex<f64>
) -> Complex<f64>
{
    let (width, height) = (lower_right.re - upper_left.re, upper_left.im - lower_right.im);
    Complex::new(
        upper_left.re + pixel.0 as f64 * width / bounds.0 as f64,
        upper_left.im - pixel.1 as f64 * height / bounds.1 as f64)
}

fn parse_pair<T: FromStr>(s: &str, separator: char) -> Option<(T, T)> {
    match s.find(separator) {
        None => None,
        Some(index) => {
            match (T::from_str(&s[..index]), T::from_str(&s[index + 1..])) {
                (Ok(l), Ok(r)) => Some((l, r)),
                _ => None,
            }
        }
    }
}

fn parse_complex(s: &str) -> Option<Complex<f64>> {
    match parse_pair(s, ',') {
        Some((re, im)) => Some(Complex::new(re, im)),
        None => None,
    }
}

fn render(pixels: &mut [u8], bounds: (usize, usize), upper_left: Complex<f64>, lower_right: Complex<f64>) {
    assert!(pixels.len() == bounds.0 * bounds.1);
    for row in 0..bounds.1 {
        for column in 0..bounds.0 {
            let point = pixel_to_point(bounds, (column, row), upper_left, lower_right);
            pixels[row * bounds.0 + column] = match escape_time(point, 255) {
                None => 0,
                Some(count) => 255 - count as u8
            };
        }
    }
}

fn write_image(filename: &str, pixels: &[u8], bounds: (usize, usize)) -> std::io::Result<()> {
    let output = File::create(filename)?;
    let encoder = PNGEncoder::new(output);
    encoder.encode(&pixels, bounds.0 as u32, bounds.1 as u32, ColorType::Palette(8))?;
    Ok(())
}

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

    let (width, height) = (args.arg_width, args.arg_height);
    let bounds = (width, height);
    let upper_left = Complex::new(args.arg_ulr, args.arg_uli);
    let lower_right = Complex::new(args.arg_lrr, args.arg_lri);
    */
    let args: Vec<String> = std::env::args().collect();
    if args.len() != 5 {
        writeln!(std::io::stderr(), "wrong number of args mofuck!").unwrap();
        std::process::exit(1);
    }
    let bounds = parse_pair(&args[2], 'x').expect("image dim fucked");
    let upper_left = parse_complex(&args[3]).expect("upper left fucked");
    let lower_right = parse_complex(&args[4]).expect("lower right fucked");
    let (width, height) = bounds;
    let mut pixels = vec![0; width * height];

    let threads = dbg!(num_cpus::get());
    let rows_per_band = height / threads + 1;
    {
        let bands: Vec<&mut [u8]> = pixels.chunks_mut(rows_per_band * width).collect();
        // blocks until all spawned threads finish
        crossbeam::scope(|spawner| {
            // into_iter gives each iteration exclusive ownership of one band
            for (i, band) in bands.into_iter().enumerate() {
                let top = rows_per_band * i;
                let end = band.len() / width;
                let band_bounds = (width, end);
                let band_upper_left = pixel_to_point(bounds, (0, top), upper_left, lower_right);
                let band_lower_right = pixel_to_point(bounds, (width, top + end), upper_left, lower_right);
                // move makes closure takes ownership of all variables it uses
                // only the closure may use mutable slice band
                spawner.spawn(move |_| {
                    render(band, band_bounds, band_upper_left, band_lower_right);
                });
            }
        }).unwrap();
    }
    write_image(&args[1], &pixels, bounds).expect("error writing PNG file");
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2018 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

extern crate enigo;
extern crate gdk;
extern crate glib_sys;
extern crate gtk;
extern crate relm_core;

use std::cell::RefCell;
use std::rc::Rc;

use enigo::{
    Enigo,
    KeyboardControllable,
    MouseButton,
    MouseControllable,
};
use gdk::{WindowExt, keyval_to_unicode};
use gdk::enums::key::{self, Key};
use gtk::{
    Cast,
    Continue,
    EditableExt,
    Entry,
    IsA,
    Object,
    Widget,
    WidgetExt,
    test_widget_wait_for_draw,
};
use relm_core::EventStream;

#[macro_export]
macro_rules! assert_text {
    ($widget:expr, $string:expr) => {
        assert_eq!($widget.get_text().unwrap(), $string.to_string());
    };
}

/// Simulate a click on a widget.
pub fn click<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W) {
    test_widget_wait_for_draw(widget);
    let allocation = widget.get_allocation();
    mouse_move(widget, allocation.width / 2, allocation.height / 2);
    let mut enigo = Enigo::new();
    enigo.mouse_click(MouseButton::Left);
    run_loop();
}

/// Simulate a double-click on a widget.
pub fn double_click<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W) {
    click(widget);
    click(widget);
}

/// Move the mouse relative to the widget position.
pub fn mouse_move<W: IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W, x: i32, y: i32) {
    test_widget_wait_for_draw(widget);
    let toplevel_window = widget.get_toplevel().and_then(|toplevel| toplevel.get_window());
    if let (Some(toplevel), Some(toplevel_window)) = (widget.get_toplevel(), toplevel_window) {
        let (_, window_x, window_y) = toplevel_window.get_origin();
        if let Some((x, y)) = widget.translate_coordinates(&toplevel, x, y) {
            let x = window_x + x;
            let y = window_y + y;
            let mut enigo = Enigo::new();
            enigo.mouse_move_to(x, y);
            run_loop();
        }
    }
}

pub fn mouse_press<W: IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W) {
    test_widget_wait_for_draw(widget);
    let allocation = widget.get_allocation();
    mouse_move(widget, allocation.width / 2, allocation.height / 2);
    let mut enigo = Enigo::new();
    enigo.mouse_down(MouseButton::Left);
    run_loop();
}

pub fn mouse_release<W: IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W) {
    test_widget_wait_for_draw(widget);
    let allocation = widget.get_allocation();
    mouse_move(widget, allocation.width / 2, allocation.height / 2);
    let mut enigo = Enigo::new();
    enigo.mouse_up(MouseButton::Left);
    run_loop();
}

pub fn enter_key<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W, key: Key) {
    test_widget_wait_for_draw(widget);
    focus(widget);
    let mut enigo = Enigo::new();
    enigo.key_click(gdk_key_to_enigo_key(key));
    run_loop();
}

pub fn enter_keys<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W, text: &str) {
    test_widget_wait_for_draw(widget);
    focus(widget);
    let mut enigo = Enigo::new();
    for char in text.chars() {
        enigo.key_sequence(&char.to_string());
        run_loop();
    }
}

pub fn focus<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W) {
    test_widget_wait_for_draw(widget);
    widget.grab_focus();
    if let Ok(entry) = widget.clone().dynamic_cast::<Entry>() {
        // Hack to make it work on Travis.
        // Should use grab_focus_without_selecting() instead.
        entry.set_position(-1);
    }
}

pub fn key_press<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W, key: Key) {
    test_widget_wait_for_draw(widget);
    focus(widget);
    let mut enigo = Enigo::new();
    enigo.key_down(gdk_key_to_enigo_key(key));
    run_loop();
}

pub fn key_release<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W, key: Key) {
    test_widget_wait_for_draw(widget);
    focus(widget);
    let mut enigo = Enigo::new();
    enigo.key_up(gdk_key_to_enigo_key(key));
    run_loop();
}

/// Wait for events the specified amount the milliseconds.
pub fn wait(ms: u32) {
    gtk::timeout_add(ms, || {
        gtk::main_quit();
        Continue(false)
    });
    gtk::main();
}

pub fn run_loop() {
    unsafe { glib_sys::g_usleep(1000) };
    while gtk::events_pending() {
        gtk::main_iteration();
    }
}

pub struct Observer<MSG> {
    result: Rc<RefCell<Option<MSG>>>,
}

impl<MSG: Clone + 'static> Observer<MSG> {
    pub fn new<F: Fn(&MSG) -> bool + 'static>(stream: &EventStream<MSG>, predicate: F) -> Self {
        let result = Rc::new(RefCell::new(None));
        let res = result.clone();
        stream.observe(move |msg| {
            if predicate(msg) {
                *res.borrow_mut() = Some(msg.clone());
            }
        });
        Self {
            result,
        }
    }

    pub fn wait(&self) -> MSG {
        loop {
            if let Ok(ref result) = self.result.try_borrow() {
                if result.is_some() {
                    break;
                }
            }
            run_loop();
        }
        self.result.borrow_mut().take()
            .expect("Message to take")
    }
}

#[macro_export]
macro_rules! observer_new {
    ($component:expr, $pat:pat) => {
        $crate::Observer::new($component.stream(), |msg|
            if let $pat = msg {
                true
            }
            else {
                false
            }
        );
    };
}

#[macro_export]
macro_rules! observer_wait {
    (let $($variant:ident)::*($name1:ident, $name2:ident $(,$rest:ident)*) = $observer:expr) => {
        let ($name1, $name2 $(, $rest)*) = {
            let msg = $observer.wait();
            if let $($variant)::*($name1, $name2 $(, $rest)*) = msg {
                ($name1, $name2 $(, $rest)*)
            }
            else {
                panic!("Wrong message type.");
            }
        };
    };
    (let $($variant:ident)::*($name:ident) = $observer:expr) => {
        let $name = {
            let msg = $observer.wait();
            if let $($variant)::*($name) = msg {
                $name
            }
            else {
                panic!("Wrong message type.");
            }
        };
    };
    (let $($variant:ident)::* = $observer:expr) => {
        let () = {
            let msg = $observer.wait();
            if let $($variant)::* = msg {
                ()
            }
            else {
                panic!("Wrong message type.");
            }
        };
    };
}

fn gdk_key_to_enigo_key(key: Key) -> enigo::Key {
    use enigo::Key::*;
    match key {
        key::Return => Return,
        key::Tab => Tab,
        key::space => Space,
        key::BackSpace => Backspace,
        key::Escape => Escape,
        key::Super_L | key::Super_R => Super,
        key::Control_L | key::Control_R => Control,
        key::Shift_L | key::Shift_R => Shift,
        key::Shift_Lock => CapsLock,
        key::Alt_L | key::Alt_R => Alt,
        key::Option => Option,
        key::Home => Home,
        key::Page_Down => PageDown,
        key::Page_Up => PageUp,
        key::leftarrow => LeftArrow,
        key::rightarrow => RightArrow,
        key::downarrow => DownArrow,
        key::uparrow => UpArrow,
        key::F1 => F1,
        key::F2 => F2,
        key::F3 => F3,
        key::F4 => F4,
        key::F5 => F5,
        key::F6 => F6,
        key::F7 => F7,
        key::F8 => F8,
        key::F9 => F9,
        key::F10 => F10,
        key::F11 => F11,
        key::F12 => F12,
        _ => {
            if let Some(char) = keyval_to_unicode(key) {
                Layout(char)
            }
            else {
                Raw(key as u16)
            }
        },
    }
}
<commit_msg>Don't focus if the widget already has the focus<commit_after>/*
 * Copyright (c) 2018 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

extern crate enigo;
extern crate gdk;
extern crate glib_sys;
extern crate gtk;
extern crate relm_core;

use std::cell::RefCell;
use std::rc::Rc;

use enigo::{
    Enigo,
    KeyboardControllable,
    MouseButton,
    MouseControllable,
};
use gdk::{WindowExt, keyval_to_unicode};
use gdk::enums::key::{self, Key};
use gtk::{
    Cast,
    Continue,
    EditableExt,
    Entry,
    IsA,
    Object,
    Widget,
    WidgetExt,
    test_widget_wait_for_draw,
};
use relm_core::EventStream;

#[macro_export]
macro_rules! assert_text {
    ($widget:expr, $string:expr) => {
        assert_eq!($widget.get_text().unwrap(), $string.to_string());
    };
}

/// Simulate a click on a widget.
pub fn click<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W) {
    test_widget_wait_for_draw(widget);
    let allocation = widget.get_allocation();
    mouse_move(widget, allocation.width / 2, allocation.height / 2);
    let mut enigo = Enigo::new();
    enigo.mouse_click(MouseButton::Left);
    run_loop();
}

/// Simulate a double-click on a widget.
pub fn double_click<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W) {
    click(widget);
    click(widget);
}

/// Move the mouse relative to the widget position.
pub fn mouse_move<W: IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W, x: i32, y: i32) {
    test_widget_wait_for_draw(widget);
    let toplevel_window = widget.get_toplevel().and_then(|toplevel| toplevel.get_window());
    if let (Some(toplevel), Some(toplevel_window)) = (widget.get_toplevel(), toplevel_window) {
        let (_, window_x, window_y) = toplevel_window.get_origin();
        if let Some((x, y)) = widget.translate_coordinates(&toplevel, x, y) {
            let x = window_x + x;
            let y = window_y + y;
            let mut enigo = Enigo::new();
            enigo.mouse_move_to(x, y);
            run_loop();
        }
    }
}

pub fn mouse_press<W: IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W) {
    test_widget_wait_for_draw(widget);
    let allocation = widget.get_allocation();
    mouse_move(widget, allocation.width / 2, allocation.height / 2);
    let mut enigo = Enigo::new();
    enigo.mouse_down(MouseButton::Left);
    run_loop();
}

pub fn mouse_release<W: IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W) {
    test_widget_wait_for_draw(widget);
    let allocation = widget.get_allocation();
    mouse_move(widget, allocation.width / 2, allocation.height / 2);
    let mut enigo = Enigo::new();
    enigo.mouse_up(MouseButton::Left);
    run_loop();
}

pub fn enter_key<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W, key: Key) {
    test_widget_wait_for_draw(widget);
    focus(widget);
    let mut enigo = Enigo::new();
    enigo.key_click(gdk_key_to_enigo_key(key));
    run_loop();
}

pub fn enter_keys<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W, text: &str) {
    test_widget_wait_for_draw(widget);
    focus(widget);
    let mut enigo = Enigo::new();
    for char in text.chars() {
        enigo.key_sequence(&char.to_string());
        run_loop();
    }
}

pub fn focus<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W) {
    test_widget_wait_for_draw(widget);
    if !widget.has_focus() {
        widget.grab_focus();
        if let Ok(entry) = widget.clone().dynamic_cast::<Entry>() {
            // Hack to make it work on Travis.
            // Should use grab_focus_without_selecting() instead.
            entry.set_position(-1);
        }
    }
}

pub fn key_press<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W, key: Key) {
    test_widget_wait_for_draw(widget);
    focus(widget);
    let mut enigo = Enigo::new();
    enigo.key_down(gdk_key_to_enigo_key(key));
    run_loop();
}

pub fn key_release<W: Clone + IsA<Object> + IsA<Widget> + WidgetExt>(widget: &W, key: Key) {
    test_widget_wait_for_draw(widget);
    focus(widget);
    let mut enigo = Enigo::new();
    enigo.key_up(gdk_key_to_enigo_key(key));
    run_loop();
}

/// Wait for events the specified amount the milliseconds.
pub fn wait(ms: u32) {
    gtk::timeout_add(ms, || {
        gtk::main_quit();
        Continue(false)
    });
    gtk::main();
}

pub fn run_loop() {
    unsafe { glib_sys::g_usleep(1000) };
    while gtk::events_pending() {
        gtk::main_iteration();
    }
}

pub struct Observer<MSG> {
    result: Rc<RefCell<Option<MSG>>>,
}

impl<MSG: Clone + 'static> Observer<MSG> {
    pub fn new<F: Fn(&MSG) -> bool + 'static>(stream: &EventStream<MSG>, predicate: F) -> Self {
        let result = Rc::new(RefCell::new(None));
        let res = result.clone();
        stream.observe(move |msg| {
            if predicate(msg) {
                *res.borrow_mut() = Some(msg.clone());
            }
        });
        Self {
            result,
        }
    }

    pub fn wait(&self) -> MSG {
        loop {
            if let Ok(ref result) = self.result.try_borrow() {
                if result.is_some() {
                    break;
                }
            }
            run_loop();
        }
        self.result.borrow_mut().take()
            .expect("Message to take")
    }
}

#[macro_export]
macro_rules! observer_new {
    ($component:expr, $pat:pat) => {
        $crate::Observer::new($component.stream(), |msg|
            if let $pat = msg {
                true
            }
            else {
                false
            }
        );
    };
}

#[macro_export]
macro_rules! observer_wait {
    (let $($variant:ident)::*($name1:ident, $name2:ident $(,$rest:ident)*) = $observer:expr) => {
        let ($name1, $name2 $(, $rest)*) = {
            let msg = $observer.wait();
            if let $($variant)::*($name1, $name2 $(, $rest)*) = msg {
                ($name1, $name2 $(, $rest)*)
            }
            else {
                panic!("Wrong message type.");
            }
        };
    };
    (let $($variant:ident)::*($name:ident) = $observer:expr) => {
        let $name = {
            let msg = $observer.wait();
            if let $($variant)::*($name) = msg {
                $name
            }
            else {
                panic!("Wrong message type.");
            }
        };
    };
    (let $($variant:ident)::* = $observer:expr) => {
        let () = {
            let msg = $observer.wait();
            if let $($variant)::* = msg {
                ()
            }
            else {
                panic!("Wrong message type.");
            }
        };
    };
}

fn gdk_key_to_enigo_key(key: Key) -> enigo::Key {
    use enigo::Key::*;
    match key {
        key::Return => Return,
        key::Tab => Tab,
        key::space => Space,
        key::BackSpace => Backspace,
        key::Escape => Escape,
        key::Super_L | key::Super_R => Super,
        key::Control_L | key::Control_R => Control,
        key::Shift_L | key::Shift_R => Shift,
        key::Shift_Lock => CapsLock,
        key::Alt_L | key::Alt_R => Alt,
        key::Option => Option,
        key::Home => Home,
        key::Page_Down => PageDown,
        key::Page_Up => PageUp,
        key::leftarrow => LeftArrow,
        key::rightarrow => RightArrow,
        key::downarrow => DownArrow,
        key::uparrow => UpArrow,
        key::F1 => F1,
        key::F2 => F2,
        key::F3 => F3,
        key::F4 => F4,
        key::F5 => F5,
        key::F6 => F6,
        key::F7 => F7,
        key::F8 => F8,
        key::F9 => F9,
        key::F10 => F10,
        key::F11 => F11,
        key::F12 => F12,
        _ => {
            if let Some(char) = keyval_to_unicode(key) {
                Layout(char)
            }
            else {
                Raw(key as u16)
            }
        },
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! In a leader based consensus algorithm, each participant maintains a block tree that looks like
//! the following in the executor:
//! ```text
//!  Height      5      6      7      ...
//!
//! Committed -> B5  -> B6  -> B7
//!         |
//!         └--> B5' -> B6' -> B7'
//!                     |
//!                     └----> B7"
//! ```
//! This module implements `SpeculationCache` that is an in-memory representation of this tree.

#[cfg(test)]
mod test;

use crate::{
    logging::{LogEntry, LogSchema},
    types::ProcessedVMOutput,
};
use anyhow::{format_err, Result};
use consensus_types::block::Block;
use diem_crypto::{hash::PRE_GENESIS_BLOCK_ID, HashValue};
use diem_infallible::Mutex;
use diem_logger::prelude::*;
use diem_types::{ledger_info::LedgerInfo, transaction::Transaction};
use executor_types::{Error, ExecutedTrees};
use std::{
    collections::HashMap,
    sync::{Arc, Weak},
};
use storage_interface::{StartupInfo, TreeState};

/// The struct that stores all speculation result of its counterpart in consensus.
pub(crate) struct SpeculationBlock {
    // The block id of which the output is computed from.
    id: HashValue,
    // The transactions in the block.
    transactions: Vec<Transaction>,
    // The pointers to all the children blocks.
    children: Vec<Arc<Mutex<SpeculationBlock>>>,
    // The speculative execution result.
    output: ProcessedVMOutput,
    // A pointer to the global block map keyed by id to achieve O(1) lookup time complexity.
    block_map: Arc<Mutex<HashMap<HashValue, Weak<Mutex<SpeculationBlock>>>>>,
}

impl SpeculationBlock {
    pub fn new(
        id: HashValue,
        transactions: Vec<Transaction>,
        output: ProcessedVMOutput,
        block_map: Arc<Mutex<HashMap<HashValue, Weak<Mutex<SpeculationBlock>>>>>,
    ) -> Self {
        Self {
            id,
            transactions,
            children: vec![],
            output,
            block_map,
        }
    }

    pub fn id(&self) -> HashValue {
        self.id
    }

    pub fn transactions(&self) -> &Vec<Transaction> {
        &self.transactions
    }

    pub fn add_child(&mut self, child: Arc<Mutex<SpeculationBlock>>) {
        self.children.push(child)
    }

    pub fn output(&self) -> &ProcessedVMOutput {
        &self.output
    }

    pub fn replace(&mut self, transactions: Vec<Transaction>, output: ProcessedVMOutput) {
        self.transactions = transactions;
        self.output = output;
        self.children = vec![];
    }
}

/// drop() will clean the current block entry from the global map.
impl Drop for SpeculationBlock {
    fn drop(&mut self) {
        self.block_map
            .lock()
            .remove(&self.id())
            .expect("Speculation block must exist in block_map before being dropped.");
        debug!(
            LogSchema::new(LogEntry::SpeculationCache).block_id(self.id()),
            "Block dropped"
        );
    }
}

/// SpeculationCache implements the block tree structrue. The tree is reprensented by a root block id,
/// all the children of root and a global block map. Each block is an Arc<Mutx<SpeculationBlock>>
/// with ref_count = 1. For the chidren of the root, the sole owner is `heads`. For the rest, the sole
/// owner is their parent block. So when a block is dropped, all its descendants will be dropped
/// recursively. In the meanwhile, wheir entries in the block map will be removed by each block's drop().
pub(crate) struct SpeculationCache {
    synced_trees: ExecutedTrees,
    committed_trees: ExecutedTrees,
    // The id of root block.
    committed_block_id: HashValue,
    // The chidren of root block.
    heads: Vec<Arc<Mutex<SpeculationBlock>>>,
    // A pointer to the global block map keyed by id to achieve O(1) lookup time complexity.
    // It is optional but an optimization.
    block_map: Arc<Mutex<HashMap<HashValue, Weak<Mutex<SpeculationBlock>>>>>,
}

impl SpeculationCache {
    pub fn new() -> Self {
        Self {
            synced_trees: ExecutedTrees::new_empty(),
            committed_trees: ExecutedTrees::new_empty(),
            heads: vec![],
            block_map: Arc::new(Mutex::new(HashMap::new())),
            committed_block_id: *PRE_GENESIS_BLOCK_ID,
        }
    }

    pub fn new_with_startup_info(startup_info: StartupInfo) -> Self {
        let mut cache = Self::new();
        let ledger_info = startup_info.latest_ledger_info.ledger_info();
        let committed_trees = ExecutedTrees::from(startup_info.committed_tree_state);
        cache.update_block_tree_root(committed_trees, ledger_info);
        if let Some(synced_tree_state) = startup_info.synced_tree_state {
            cache.update_synced_trees(ExecutedTrees::from(synced_tree_state));
        }
        cache
    }

    pub fn new_for_db_bootstrapping(tree_state: TreeState) -> Self {
        // The DB-bootstrapper applies genesis txn on a local DB and create a waypoint,
        // assuming everything is synced and committed.
        let executor_trees = ExecutedTrees::from(tree_state);
        Self {
            synced_trees: executor_trees.clone(),
            committed_trees: executor_trees,
            heads: vec![],
            block_map: Arc::new(Mutex::new(HashMap::new())),
            committed_block_id: *PRE_GENESIS_BLOCK_ID,
        }
    }

    pub fn committed_block_id(&self) -> HashValue {
        self.committed_block_id
    }

    pub fn committed_trees(&self) -> &ExecutedTrees {
        &self.committed_trees
    }

    pub fn synced_trees(&self) -> &ExecutedTrees {
        &self.synced_trees
    }

    pub fn update_block_tree_root(
        &mut self,
        committed_trees: ExecutedTrees,
        committed_ledger_info: &LedgerInfo,
    ) {
        let new_root_block_id = if committed_ledger_info.ends_epoch() {
            // Update the root block id with reconfig virtual block id, to be consistent
            // with the logic of Consensus.
            let id = Block::make_genesis_block_from_ledger_info(committed_ledger_info).id();
            info!(
                LogSchema::new(LogEntry::SpeculationCache)
                    .root_block_id(id)
                    .original_reconfiguration_block_id(committed_ledger_info.consensus_block_id()),
                "Updated with a new root block as a virtual block of reconfiguration block"
            );
            id
        } else {
            let id = committed_ledger_info.consensus_block_id();
            info!(
                LogSchema::new(LogEntry::SpeculationCache).root_block_id(id),
                "Updated with a new root block",
            );
            id
        };
        self.committed_block_id = new_root_block_id;
        self.committed_trees = committed_trees.clone();
        self.synced_trees = committed_trees;
    }

    pub fn update_synced_trees(&mut self, new_trees: ExecutedTrees) {
        self.synced_trees = new_trees;
    }

    pub fn reset(&mut self) {
        self.heads = vec![];
        *self.block_map.lock() = HashMap::new();
    }

    pub fn add_block(
        &mut self,
        parent_block_id: HashValue,
        block: (
            HashValue,         /* block id */
            Vec<Transaction>,  /* block transactions */
            ProcessedVMOutput, /* block execution output */
        ),
    ) -> Result<(), Error> {
        // Check existence first
        let (block_id, txns, output) = block;

        // If block is re-executed, update it.
        let old_block = self
            .block_map
            .lock()
            .get(&block_id)
            .map(|b| {
                b.upgrade().ok_or_else(|| {
                    format_err!(
                        "block {:x} has been deallocated. Something went wrong.",
                        block_id
                    )
                })
            })
            .transpose()?;

        if let Some(old_block) = old_block {
            old_block.lock().replace(txns, output);
            return Ok(());
        }

        let new_block = Arc::new(Mutex::new(SpeculationBlock::new(
            block_id,
            txns,
            output,
            Arc::clone(&self.block_map),
        )));
        // Add to the map
        self.block_map
            .lock()
            .insert(block_id, Arc::downgrade(&new_block));
        // Add to the tree
        if parent_block_id == self.committed_block_id() {
            self.heads.push(new_block);
        } else {
            self.get_block(&parent_block_id)?
                .lock()
                .add_child(new_block);
        }
        Ok(())
    }

    pub fn prune(&mut self, committed_ledger_info: &LedgerInfo) -> Result<(), Error> {
        let arc_latest_committed_block =
            self.get_block(&committed_ledger_info.consensus_block_id())?;
        let latest_committed_block = arc_latest_committed_block.lock();
        self.heads = latest_committed_block.children.clone();
        self.update_block_tree_root(
            latest_committed_block.output().executed_trees().clone(),
            committed_ledger_info,
        );
        Ok(())
    }

    // This function is intended to be called internally.
    pub fn get_block(&self, block_id: &HashValue) -> Result<Arc<Mutex<SpeculationBlock>>, Error> {
        Ok(self
            .block_map
            .lock()
            .get(block_id)
            .ok_or_else(|| Error::BlockNotFound(*block_id))?
            .upgrade()
            .ok_or_else(|| {
                format_err!(
                    "block {:x} has been deallocated. Something went wrong.",
                    block_id
                )
            })?)
    }
}
<commit_msg>[executor] ensure no leaked references to blocks before pruning<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! In a leader based consensus algorithm, each participant maintains a block tree that looks like
//! the following in the executor:
//! ```text
//!  Height      5      6      7      ...
//!
//! Committed -> B5  -> B6  -> B7
//!         |
//!         └--> B5' -> B6' -> B7'
//!                     |
//!                     └----> B7"
//! ```
//! This module implements `SpeculationCache` that is an in-memory representation of this tree.

#[cfg(test)]
mod test;

use crate::{
    logging::{LogEntry, LogSchema},
    types::ProcessedVMOutput,
};
use anyhow::{format_err, Result};
use consensus_types::block::Block;
use diem_crypto::{hash::PRE_GENESIS_BLOCK_ID, HashValue};
use diem_infallible::Mutex;
use diem_logger::prelude::*;
use diem_types::{ledger_info::LedgerInfo, transaction::Transaction};
use executor_types::{Error, ExecutedTrees};
use std::{
    collections::HashMap,
    sync::{Arc, Weak},
};
use storage_interface::{StartupInfo, TreeState};

/// The struct that stores all speculation result of its counterpart in consensus.
pub(crate) struct SpeculationBlock {
    // The block id of which the output is computed from.
    id: HashValue,
    // The transactions in the block.
    transactions: Vec<Transaction>,
    // The pointers to all the children blocks.
    children: Vec<Arc<Mutex<SpeculationBlock>>>,
    // The speculative execution result.
    output: ProcessedVMOutput,
    // A pointer to the global block map keyed by id to achieve O(1) lookup time complexity.
    block_map: Arc<Mutex<HashMap<HashValue, Weak<Mutex<SpeculationBlock>>>>>,
}

impl SpeculationBlock {
    pub fn new(
        id: HashValue,
        transactions: Vec<Transaction>,
        output: ProcessedVMOutput,
        block_map: Arc<Mutex<HashMap<HashValue, Weak<Mutex<SpeculationBlock>>>>>,
    ) -> Self {
        Self {
            id,
            transactions,
            children: vec![],
            output,
            block_map,
        }
    }

    pub fn id(&self) -> HashValue {
        self.id
    }

    pub fn transactions(&self) -> &Vec<Transaction> {
        &self.transactions
    }

    pub fn add_child(&mut self, child: Arc<Mutex<SpeculationBlock>>) {
        self.children.push(child)
    }

    pub fn output(&self) -> &ProcessedVMOutput {
        &self.output
    }

    pub fn replace(&mut self, transactions: Vec<Transaction>, output: ProcessedVMOutput) {
        self.transactions = transactions;
        self.output = output;
        self.children = vec![];
    }
}

/// drop() will clean the current block entry from the global map.
impl Drop for SpeculationBlock {
    fn drop(&mut self) {
        self.block_map
            .lock()
            .remove(&self.id())
            .expect("Speculation block must exist in block_map before being dropped.");
        debug!(
            LogSchema::new(LogEntry::SpeculationCache).block_id(self.id()),
            "Block dropped"
        );
    }
}

/// SpeculationCache implements the block tree structrue. The tree is reprensented by a root block id,
/// all the children of root and a global block map. Each block is an Arc<Mutx<SpeculationBlock>>
/// with ref_count = 1. For the chidren of the root, the sole owner is `heads`. For the rest, the sole
/// owner is their parent block. So when a block is dropped, all its descendants will be dropped
/// recursively. In the meanwhile, wheir entries in the block map will be removed by each block's drop().
pub(crate) struct SpeculationCache {
    synced_trees: ExecutedTrees,
    committed_trees: ExecutedTrees,
    // The id of root block.
    committed_block_id: HashValue,
    // The chidren of root block.
    heads: Vec<Arc<Mutex<SpeculationBlock>>>,
    // A pointer to the global block map keyed by id to achieve O(1) lookup time complexity.
    // It is optional but an optimization.
    block_map: Arc<Mutex<HashMap<HashValue, Weak<Mutex<SpeculationBlock>>>>>,
}

impl SpeculationCache {
    pub fn new() -> Self {
        Self {
            synced_trees: ExecutedTrees::new_empty(),
            committed_trees: ExecutedTrees::new_empty(),
            heads: vec![],
            block_map: Arc::new(Mutex::new(HashMap::new())),
            committed_block_id: *PRE_GENESIS_BLOCK_ID,
        }
    }

    pub fn new_with_startup_info(startup_info: StartupInfo) -> Self {
        let mut cache = Self::new();
        let ledger_info = startup_info.latest_ledger_info.ledger_info();
        let committed_trees = ExecutedTrees::from(startup_info.committed_tree_state);
        cache.update_block_tree_root(committed_trees, ledger_info);
        if let Some(synced_tree_state) = startup_info.synced_tree_state {
            cache.update_synced_trees(ExecutedTrees::from(synced_tree_state));
        }
        cache
    }

    pub fn new_for_db_bootstrapping(tree_state: TreeState) -> Self {
        // The DB-bootstrapper applies genesis txn on a local DB and create a waypoint,
        // assuming everything is synced and committed.
        let executor_trees = ExecutedTrees::from(tree_state);
        Self {
            synced_trees: executor_trees.clone(),
            committed_trees: executor_trees,
            heads: vec![],
            block_map: Arc::new(Mutex::new(HashMap::new())),
            committed_block_id: *PRE_GENESIS_BLOCK_ID,
        }
    }

    pub fn committed_block_id(&self) -> HashValue {
        self.committed_block_id
    }

    pub fn committed_trees(&self) -> &ExecutedTrees {
        &self.committed_trees
    }

    pub fn synced_trees(&self) -> &ExecutedTrees {
        &self.synced_trees
    }

    pub fn update_block_tree_root(
        &mut self,
        committed_trees: ExecutedTrees,
        committed_ledger_info: &LedgerInfo,
    ) {
        let new_root_block_id = if committed_ledger_info.ends_epoch() {
            // Update the root block id with reconfig virtual block id, to be consistent
            // with the logic of Consensus.
            let id = Block::make_genesis_block_from_ledger_info(committed_ledger_info).id();
            info!(
                LogSchema::new(LogEntry::SpeculationCache)
                    .root_block_id(id)
                    .original_reconfiguration_block_id(committed_ledger_info.consensus_block_id()),
                "Updated with a new root block as a virtual block of reconfiguration block"
            );
            id
        } else {
            let id = committed_ledger_info.consensus_block_id();
            info!(
                LogSchema::new(LogEntry::SpeculationCache).root_block_id(id),
                "Updated with a new root block",
            );
            id
        };
        self.committed_block_id = new_root_block_id;
        self.committed_trees = committed_trees.clone();
        self.synced_trees = committed_trees;
    }

    pub fn update_synced_trees(&mut self, new_trees: ExecutedTrees) {
        self.synced_trees = new_trees;
    }

    pub fn reset(&mut self) {
        self.heads = vec![];
        *self.block_map.lock() = HashMap::new();
    }

    pub fn add_block(
        &mut self,
        parent_block_id: HashValue,
        block: (
            HashValue,         /* block id */
            Vec<Transaction>,  /* block transactions */
            ProcessedVMOutput, /* block execution output */
        ),
    ) -> Result<(), Error> {
        // Check existence first
        let (block_id, txns, output) = block;

        // If block is re-executed, update it.
        let old_block = self
            .block_map
            .lock()
            .get(&block_id)
            .map(|b| {
                b.upgrade().ok_or_else(|| {
                    format_err!(
                        "block {:x} has been deallocated. Something went wrong.",
                        block_id
                    )
                })
            })
            .transpose()?;

        if let Some(old_block) = old_block {
            old_block.lock().replace(txns, output);
            return Ok(());
        }

        let new_block = Arc::new(Mutex::new(SpeculationBlock::new(
            block_id,
            txns,
            output,
            Arc::clone(&self.block_map),
        )));
        // Add to the map
        self.block_map
            .lock()
            .insert(block_id, Arc::downgrade(&new_block));
        // Add to the tree
        if parent_block_id == self.committed_block_id() {
            self.heads.push(new_block);
        } else {
            self.get_block(&parent_block_id)?
                .lock()
                .add_child(new_block);
        }
        Ok(())
    }

    pub fn prune(&mut self, committed_ledger_info: &LedgerInfo) -> Result<(), Error> {
        let (heads, executed_trees) = {
            let latest_committed_block =
                self.get_block(&committed_ledger_info.consensus_block_id())?;
            let locked = latest_committed_block.lock();

            (
                locked.children.clone(),
                locked.output().executed_trees().clone(),
            )
        };

        // being defensive here: a leaked block ref being dropped out of the lock can cause
        // weakly reffed SMT nodes go away out of the lock unexpectedly.
        if !self.heads.iter().all(|h| Arc::strong_count(h) == 1) {
            panic!("Block ref leaked: there are still references out there of blocks to be pruned.")
        }
        self.heads = heads;
        self.update_block_tree_root(executed_trees, committed_ledger_info);
        Ok(())
    }

    // This function is intended to be called internally.
    pub fn get_block(&self, block_id: &HashValue) -> Result<Arc<Mutex<SpeculationBlock>>, Error> {
        Ok(self
            .block_map
            .lock()
            .get(block_id)
            .ok_or_else(|| Error::BlockNotFound(*block_id))?
            .upgrade()
            .ok_or_else(|| {
                format_err!(
                    "block {:x} has been deallocated. Something went wrong.",
                    block_id
                )
            })?)
    }
}
<|endoftext|>


<commit_before>use command_prelude::*;

use cargo::ops;

pub fn cli() -> App {
    subcommand("uninstall")
        .about("Remove a Rust binary")
        .arg(Arg::with_name("spec").multiple(true))
        .arg(multi_opt("bin", "NAME", "Only uninstall the binary NAME"))
        .arg(opt("root", "Directory to uninstall packages from").value_name("DIR"))
        .after_help(
            "\
The argument SPEC is a package id specification (see `cargo help pkgid`) to
specify which crate should be uninstalled. By default all binaries are
uninstalled for a crate but the `--bin` and `--example` flags can be used to
only uninstall particular binaries.
",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
    let root = args.value_of("root");
    let specs = args.values_of("spec").unwrap_or_default().collect();
    ops::uninstall(root, specs, &values(args, "bin"), config)?;
    Ok(())
}
<commit_msg>Allow `-p` in `uninstall` to accommodate error messages.<commit_after>use command_prelude::*;

use cargo::ops;

pub fn cli() -> App {
    subcommand("uninstall")
        .about("Remove a Rust binary")
        .arg(Arg::with_name("spec").multiple(true))
        .arg_package_spec_simple("Package to uninstall")
        .arg(multi_opt("bin", "NAME", "Only uninstall the binary NAME"))
        .arg(opt("root", "Directory to uninstall packages from").value_name("DIR"))
        .after_help(
            "\
The argument SPEC is a package id specification (see `cargo help pkgid`) to
specify which crate should be uninstalled. By default all binaries are
uninstalled for a crate but the `--bin` and `--example` flags can be used to
only uninstall particular binaries.
",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
    let root = args.value_of("root");
    let specs = args
        .values_of("spec")
        .unwrap_or_else(|| args.values_of("package").unwrap_or_default())
        .collect();
    ops::uninstall(root, specs, &values(args, "bin"), config)?;
    Ok(())
}
<|endoftext|>


<commit_before>const USAGE: &'static str = "
Usage: mergesort bench [--size N]
       mergesort --help

Parallel mergesort: regular sorting with a parallel merge step.
O(n log n) time; O(n) extra space; critical path is O(log^3 n)

Algorithm described in: https://software.intel.com/en-us/articles/a-parallel-stable-sort-using-c11-for-tbb-cilk-plus-and-openmp

Commands:
    bench              Run the benchmark in different modes and print the timings.

Options:
    --size N           Number of 32-bit words to sort [default: 250000000] (1GB)
    -h, --help         Show this message.
";

#[derive(RustcDecodable)]
pub struct Args {
    cmd_bench: bool,
    flag_size: usize,
}

use docopt::Docopt;
use rayon;

use std::cmp::max;
use std::time::Instant;

pub fn merge_sort<T: Ord + Send + Copy>(v: &mut [T]) {
    let n = v.len();
    let mut buf = Vec::with_capacity(n);
    // We always overwrite the buffer before reading to it, and letting rust
    // initialize it would increase the critical path to O(n).
    unsafe {
        buf.set_len(n);
    }
    rsort(v, &mut buf[..]);
}

// Values from manual tuning gigasort on one machine.
const SORT_CHUNK: usize = 32 * 1024;
const MERGE_CHUNK: usize = 64 * 1024;

// Sort src, possibly making use of identically sized buf.
fn rsort<T: Ord + Send + Copy>(src: &mut [T], buf: &mut [T]) {
    if src.len() <= SORT_CHUNK {
        src.sort();
        return;
    }

    // Sort each half into half of the buffer.
    let mid = src.len() / 2;
    let (bufa, bufb) = buf.split_at_mut(mid);
    {
        let (sa, sb) = src.split_at_mut(mid);
        rayon::join(|| rsort_into(sa, bufa), || rsort_into(sb, bufb));
    }

    // Merge the buffer halves back into the original.
    rmerge(bufa, bufb, src);
}

// Sort src, putting the result into dest.
fn rsort_into<T: Ord + Send + Copy>(src: &mut [T], dest: &mut [T]) {
    let mid = src.len() / 2;
    let (s1, s2) = src.split_at_mut(mid);
    {
        // Sort each half.
        let (d1, d2) = dest.split_at_mut(mid);
        rayon::join(|| rsort(s1, d1), || rsort(s2, d2));
    }

    // Merge the halves into dest.
    rmerge(s1, s2, dest);
}

// Merge sorted inputs a and b, putting result in dest.
//
// Note: `a` and `b` have type `&mut [T]` and not `&[T]` because we do
// not want to require a `T: Sync` bound. Using `&mut` references
// proves to the compiler that we are not sharing `a` and `b` across
// threads and thus we only need a `T: Send` bound.
fn rmerge<T: Ord + Send + Copy>(a: &mut [T], b: &mut [T], dest: &mut [T]) {
    // Swap so a is always longer.
    let (a, b) = if a.len() > b.len() {
        (a, b)
    } else {
        (b, a)
    };
    if dest.len() <= MERGE_CHUNK {
        seq_merge(a, b, dest);
        return;
    }

    // Find the middle element of the longer list, and
    // use binary search to find its location in the shorter list.
    let ma = a.len() / 2;
    let mb = match b.binary_search(&a[ma]) {
        Ok(i) => i,
        Err(i) => i,
    };

    let (a1, a2) = a.split_at_mut(ma);
    let (b1, b2) = b.split_at_mut(mb);
    let (d1, d2) = dest.split_at_mut(ma + mb);
    rayon::join(|| rmerge(a1, b1, d1), || rmerge(a2, b2, d2));
}

// Merges sorted a and b into sorted dest.
#[inline(never)]
fn seq_merge<T: Ord + Copy>(a: &[T], b: &[T], dest: &mut [T]) {
    if b.is_empty() {
        dest.copy_from_slice(a);
        return;
    }
    let biggest = max(*a.last().unwrap(), *b.last().unwrap());
    let mut ai = a.iter();
    let mut an = *ai.next().unwrap();
    let mut bi = b.iter();
    let mut bn = *bi.next().unwrap();
    for d in dest.iter_mut() {
        if an < bn {
            *d = an;
            an = match ai.next() {
                Some(x) => *x,
                None => biggest,
            }
        } else {
            *d = bn;
            bn = match bi.next() {
                Some(x) => *x,
                None => biggest,
            }
        }
    }
}

#[test]
fn test_merge_sort() {
    let mut v = vec![1; 200_000];
    merge_sort(&mut v[..]);

    let sorted: Vec<u32> = (1..1_000_000).collect();
    let mut v = sorted.clone();
    merge_sort(&mut v[..]);
    assert_eq!(sorted, v);

    v.reverse();
    merge_sort(&mut v[..]);
    assert_eq!(sorted, v);
}

pub fn seq_merge_sort<T: Ord + Copy>(v: &mut [T]) {
    let n = v.len();
    let mut buf = Vec::with_capacity(n);
    // We always overwrite the buffer before reading to it, and we want to
    // duplicate the behavior of parallel sort.
    unsafe {
        buf.set_len(n);
    }
    seq_sort(v, &mut buf[..]);
}

// Sort src, possibly making use of identically sized buf.
fn seq_sort<T: Ord + Copy>(src: &mut [T], buf: &mut [T]) {
    if src.len() <= SORT_CHUNK {
        src.sort();
        return;
    }

    // Sort each half into half of the buffer.
    let mid = src.len() / 2;
    let (bufa, bufb) = buf.split_at_mut(mid);
    {
        let (sa, sb) = src.split_at_mut(mid);
        seq_sort_into(sa, bufa);
        seq_sort_into(sb, bufb);
    }

    // Merge the buffer halves back into the original.
    seq_merge(bufa, bufb, src);
}

// Sort src, putting the result into dest.
fn seq_sort_into<T: Ord + Copy>(src: &mut [T], dest: &mut [T]) {
    let mid = src.len() / 2;
    let (s1, s2) = src.split_at_mut(mid);
    {
        // Sort each half.
        let (d1, d2) = dest.split_at_mut(mid);
        seq_sort(s1, d1);
        seq_sort(s2, d2);
    }

    // Merge the halves into dest.
    seq_merge(s1, s2, dest);
}

pub fn is_sorted<T: Send + Ord>(v: &mut [T]) -> bool {
    let n = v.len();
    if n <= SORT_CHUNK {
        for i in 1..n {
            if v[i - 1] > v[i] {
                return false;
            }
        }
        return true;
    }

    let mid = n / 2;
    if v[mid - 1] > v[mid] {
        return false;
    }
    let (a, b) = v.split_at_mut(mid);
    let (left, right) = rayon::join(|| is_sorted(a), || is_sorted(b));
    return left && right;
}

fn default_vec(n: usize) -> Vec<u32> {
    let mut v = Vec::<u32>::with_capacity(n);
    // Populate with unique, pseudorandom values.
    let mut m = 1;
    for _ in 0..n {
        v.push(m);
        m = m.wrapping_mul(101);
    }
    v
}

fn timed_sort<F: FnOnce(&mut [u32])>(n: usize, f: F, name: &str) -> u64 {
    let mut v = default_vec(n);

    let start = Instant::now();
    f(&mut v[..]);
    let dur = Instant::now() - start;
    let nanos = dur.subsec_nanos() as u64 + dur.as_secs() * 1_000_000_000u64;
    println!("{}: sorted {} ints: {} s", name, n, nanos as f32 / 1e9f32);

    // Check correctness
    assert!(is_sorted(&mut v[..]));

    return nanos
}

pub fn main(args: &[String]) {
    let args: Args =
        Docopt::new(USAGE)
            .and_then(|d| d.argv(args).decode())
            .unwrap_or_else(|e| e.exit());

    if args.cmd_bench {
        let seq = timed_sort(args.flag_size, seq_merge_sort, "seq");
        let par = timed_sort(args.flag_size, merge_sort, "par");
        let speedup = seq as f64 / par as f64;
        println!("speedup: {:.2}x", speedup);
    }
}

#[cfg(test)]
mod bench;
<commit_msg>use the same data for mergesort as quicksort<commit_after>use rand::{Rng, SeedableRng, XorShiftRng};

const USAGE: &'static str = "
Usage: mergesort bench [--size N]
       mergesort --help

Parallel mergesort: regular sorting with a parallel merge step.
O(n log n) time; O(n) extra space; critical path is O(log^3 n)

Algorithm described in: https://software.intel.com/en-us/articles/a-parallel-stable-sort-using-c11-for-tbb-cilk-plus-and-openmp

Commands:
    bench              Run the benchmark in different modes and print the timings.

Options:
    --size N           Number of 32-bit words to sort [default: 250000000] (1GB)
    -h, --help         Show this message.
";

#[derive(RustcDecodable)]
pub struct Args {
    cmd_bench: bool,
    flag_size: usize,
}

use docopt::Docopt;
use rayon;

use std::cmp::max;
use std::time::Instant;

pub fn merge_sort<T: Ord + Send + Copy>(v: &mut [T]) {
    let n = v.len();
    let mut buf = Vec::with_capacity(n);
    // We always overwrite the buffer before reading to it, and letting rust
    // initialize it would increase the critical path to O(n).
    unsafe {
        buf.set_len(n);
    }
    rsort(v, &mut buf[..]);
}

// Values from manual tuning gigasort on one machine.
const SORT_CHUNK: usize = 32 * 1024;
const MERGE_CHUNK: usize = 64 * 1024;

// Sort src, possibly making use of identically sized buf.
fn rsort<T: Ord + Send + Copy>(src: &mut [T], buf: &mut [T]) {
    if src.len() <= SORT_CHUNK {
        src.sort();
        return;
    }

    // Sort each half into half of the buffer.
    let mid = src.len() / 2;
    let (bufa, bufb) = buf.split_at_mut(mid);
    {
        let (sa, sb) = src.split_at_mut(mid);
        rayon::join(|| rsort_into(sa, bufa), || rsort_into(sb, bufb));
    }

    // Merge the buffer halves back into the original.
    rmerge(bufa, bufb, src);
}

// Sort src, putting the result into dest.
fn rsort_into<T: Ord + Send + Copy>(src: &mut [T], dest: &mut [T]) {
    let mid = src.len() / 2;
    let (s1, s2) = src.split_at_mut(mid);
    {
        // Sort each half.
        let (d1, d2) = dest.split_at_mut(mid);
        rayon::join(|| rsort(s1, d1), || rsort(s2, d2));
    }

    // Merge the halves into dest.
    rmerge(s1, s2, dest);
}

// Merge sorted inputs a and b, putting result in dest.
//
// Note: `a` and `b` have type `&mut [T]` and not `&[T]` because we do
// not want to require a `T: Sync` bound. Using `&mut` references
// proves to the compiler that we are not sharing `a` and `b` across
// threads and thus we only need a `T: Send` bound.
fn rmerge<T: Ord + Send + Copy>(a: &mut [T], b: &mut [T], dest: &mut [T]) {
    // Swap so a is always longer.
    let (a, b) = if a.len() > b.len() {
        (a, b)
    } else {
        (b, a)
    };
    if dest.len() <= MERGE_CHUNK {
        seq_merge(a, b, dest);
        return;
    }

    // Find the middle element of the longer list, and
    // use binary search to find its location in the shorter list.
    let ma = a.len() / 2;
    let mb = match b.binary_search(&a[ma]) {
        Ok(i) => i,
        Err(i) => i,
    };

    let (a1, a2) = a.split_at_mut(ma);
    let (b1, b2) = b.split_at_mut(mb);
    let (d1, d2) = dest.split_at_mut(ma + mb);
    rayon::join(|| rmerge(a1, b1, d1), || rmerge(a2, b2, d2));
}

// Merges sorted a and b into sorted dest.
#[inline(never)]
fn seq_merge<T: Ord + Copy>(a: &[T], b: &[T], dest: &mut [T]) {
    if b.is_empty() {
        dest.copy_from_slice(a);
        return;
    }
    let biggest = max(*a.last().unwrap(), *b.last().unwrap());
    let mut ai = a.iter();
    let mut an = *ai.next().unwrap();
    let mut bi = b.iter();
    let mut bn = *bi.next().unwrap();
    for d in dest.iter_mut() {
        if an < bn {
            *d = an;
            an = match ai.next() {
                Some(x) => *x,
                None => biggest,
            }
        } else {
            *d = bn;
            bn = match bi.next() {
                Some(x) => *x,
                None => biggest,
            }
        }
    }
}

#[test]
fn test_merge_sort() {
    let mut v = vec![1; 200_000];
    merge_sort(&mut v[..]);

    let sorted: Vec<u32> = (1..1_000_000).collect();
    let mut v = sorted.clone();
    merge_sort(&mut v[..]);
    assert_eq!(sorted, v);

    v.reverse();
    merge_sort(&mut v[..]);
    assert_eq!(sorted, v);
}

pub fn seq_merge_sort<T: Ord + Copy>(v: &mut [T]) {
    let n = v.len();
    let mut buf = Vec::with_capacity(n);
    // We always overwrite the buffer before reading to it, and we want to
    // duplicate the behavior of parallel sort.
    unsafe {
        buf.set_len(n);
    }
    seq_sort(v, &mut buf[..]);
}

// Sort src, possibly making use of identically sized buf.
fn seq_sort<T: Ord + Copy>(src: &mut [T], buf: &mut [T]) {
    if src.len() <= SORT_CHUNK {
        src.sort();
        return;
    }

    // Sort each half into half of the buffer.
    let mid = src.len() / 2;
    let (bufa, bufb) = buf.split_at_mut(mid);
    {
        let (sa, sb) = src.split_at_mut(mid);
        seq_sort_into(sa, bufa);
        seq_sort_into(sb, bufb);
    }

    // Merge the buffer halves back into the original.
    seq_merge(bufa, bufb, src);
}

// Sort src, putting the result into dest.
fn seq_sort_into<T: Ord + Copy>(src: &mut [T], dest: &mut [T]) {
    let mid = src.len() / 2;
    let (s1, s2) = src.split_at_mut(mid);
    {
        // Sort each half.
        let (d1, d2) = dest.split_at_mut(mid);
        seq_sort(s1, d1);
        seq_sort(s2, d2);
    }

    // Merge the halves into dest.
    seq_merge(s1, s2, dest);
}

pub fn is_sorted<T: Send + Ord>(v: &mut [T]) -> bool {
    let n = v.len();
    if n <= SORT_CHUNK {
        for i in 1..n {
            if v[i - 1] > v[i] {
                return false;
            }
        }
        return true;
    }

    let mid = n / 2;
    if v[mid - 1] > v[mid] {
        return false;
    }
    let (a, b) = v.split_at_mut(mid);
    let (left, right) = rayon::join(|| is_sorted(a), || is_sorted(b));
    return left && right;
}

fn default_vec(n: usize) -> Vec<u32> {
    let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
    (0..n).map(|_| rng.next_u32()).collect()
}

fn timed_sort<F: FnOnce(&mut [u32])>(n: usize, f: F, name: &str) -> u64 {
    let mut v = default_vec(n);

    let start = Instant::now();
    f(&mut v[..]);
    let dur = Instant::now() - start;
    let nanos = dur.subsec_nanos() as u64 + dur.as_secs() * 1_000_000_000u64;
    println!("{}: sorted {} ints: {} s", name, n, nanos as f32 / 1e9f32);

    // Check correctness
    assert!(is_sorted(&mut v[..]));

    return nanos
}

pub fn main(args: &[String]) {
    let args: Args =
        Docopt::new(USAGE)
            .and_then(|d| d.argv(args).decode())
            .unwrap_or_else(|e| e.exit());

    if args.cmd_bench {
        let seq = timed_sort(args.flag_size, seq_merge_sort, "seq");
        let par = timed_sort(args.flag_size, merge_sort, "par");
        let speedup = seq as f64 / par as f64;
        println!("speedup: {:.2}x", speedup);
    }
}

#[cfg(test)]
mod bench;
<|endoftext|>


<commit_before>use crate::ast::Field;
use crate::attr::{Display, Trait};
use proc_macro2::TokenTree;
use quote::{format_ident, quote_spanned};
use std::collections::{BTreeSet as Set, HashMap as Map};
use syn::ext::IdentExt;
use syn::parse::{ParseStream, Parser};
use syn::{Ident, Index, LitStr, Member, Result, Token};

impl Display<'_> {
    // Transform `"error {var}"` to `"error {}", var`.
    pub fn expand_shorthand(&mut self, fields: &[Field]) {
        let raw_args = self.args.clone();
        let mut named_args = explicit_named_args.parse2(raw_args).unwrap();
        let mut member_index = Map::new();
        for (i, field) in fields.iter().enumerate() {
            member_index.insert(field.member.clone(), i);
        }

        let span = self.fmt.span();
        let fmt = self.fmt.value();
        let mut read = fmt.as_str();
        let mut out = String::new();
        let mut args = self.args.clone();
        let mut has_bonus_display = false;
        let mut implied_bounds = Set::new();

        let mut has_trailing_comma = false;
        if let Some(TokenTree::Punct(punct)) = args.clone().into_iter().last() {
            if punct.as_char() == ',' {
                has_trailing_comma = true;
            }
        }

        while let Some(brace) = read.find('{') {
            out += &read[..brace + 1];
            read = &read[brace + 1..];
            if read.starts_with('{') {
                out.push('{');
                read = &read[1..];
                continue;
            }
            let next = match read.chars().next() {
                Some(next) => next,
                None => return,
            };
            let member = match next {
                '0'..='9' => {
                    let int = take_int(&mut read);
                    let member = match int.parse::<u32>() {
                        Ok(index) => Member::Unnamed(Index { index, span }),
                        Err(_) => return,
                    };
                    if !member_index.contains_key(&member) {
                        out += ∫
                        continue;
                    }
                    member
                }
                'a'..='z' | 'A'..='Z' | '_' => {
                    let mut ident = take_ident(&mut read);
                    ident.set_span(span);
                    Member::Named(ident)
                }
                _ => continue,
            };
            let local = match &member {
                Member::Unnamed(index) => format_ident!("_{}", index),
                Member::Named(ident) => ident.clone(),
            };
            let mut formatvar = local.clone();
            if formatvar.to_string().starts_with("r#") {
                formatvar = format_ident!("r_{}", formatvar);
            }
            if formatvar.to_string().starts_with('_') {
                // Work around leading underscore being rejected by 1.40 and
                // older compilers. https://github.com/rust-lang/rust/pull/66847
                formatvar = format_ident!("field_{}", formatvar);
            }
            out += &formatvar.to_string();
            if !named_args.insert(formatvar.clone()) {
                // Already specified in the format argument list.
                continue;
            }
            if !has_trailing_comma {
                args.extend(quote_spanned!(span=> ,));
            }
            args.extend(quote_spanned!(span=> #formatvar = #local));
            if let Some(&field) = member_index.get(&member) {
                let end_spec = match read.find('}') {
                    Some(end_spec) => end_spec,
                    None => return,
                };
                let bound = match read[..end_spec].chars().next_back() {
                    Some('?') => Trait::Debug,
                    Some('o') => Trait::Octal,
                    Some('x') => Trait::LowerHex,
                    Some('X') => Trait::UpperHex,
                    Some('p') => Trait::Pointer,
                    Some('b') => Trait::Binary,
                    Some('e') => Trait::LowerExp,
                    Some('E') => Trait::UpperExp,
                    Some(_) => Trait::Display,
                    None => {
                        has_bonus_display = true;
                        args.extend(quote_spanned!(span=> .as_display()));
                        Trait::Display
                    }
                };
                implied_bounds.insert((field, bound));
            }
            has_trailing_comma = false;
        }

        out += read;
        self.fmt = LitStr::new(&out, self.fmt.span());
        self.args = args;
        self.has_bonus_display = has_bonus_display;
        self.implied_bounds = implied_bounds;
    }
}

fn explicit_named_args(input: ParseStream) -> Result<Set<Ident>> {
    let mut named_args = Set::new();

    while !input.is_empty() {
        if input.peek(Token![,]) && input.peek2(Ident::peek_any) && input.peek3(Token![=]) {
            input.parse::<Token![,]>()?;
            let ident = input.call(Ident::parse_any)?;
            input.parse::<Token![=]>()?;
            named_args.insert(ident);
        } else {
            input.parse::<TokenTree>()?;
        }
    }

    Ok(named_args)
}

fn take_int(read: &mut &str) -> String {
    let mut int = String::new();
    for (i, ch) in read.char_indices() {
        match ch {
            '0'..='9' => int.push(ch),
            _ => {
                *read = &read[i..];
                break;
            }
        }
    }
    int
}

fn take_ident(read: &mut &str) -> Ident {
    let mut ident = String::new();
    let raw = read.starts_with("r#");
    if raw {
        ident.push_str("r#");
        *read = &read[2..];
    }
    for (i, ch) in read.char_indices() {
        match ch {
            'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident.push(ch),
            _ => {
                *read = &read[i..];
                break;
            }
        }
    }
    Ident::parse_any.parse_str(&ident).unwrap()
}
<commit_msg>Handle multiple bounds from the same format string on the same field<commit_after>use crate::ast::Field;
use crate::attr::{Display, Trait};
use proc_macro2::TokenTree;
use quote::{format_ident, quote_spanned};
use std::collections::{BTreeSet as Set, HashMap as Map};
use syn::ext::IdentExt;
use syn::parse::{ParseStream, Parser};
use syn::{Ident, Index, LitStr, Member, Result, Token};

impl Display<'_> {
    // Transform `"error {var}"` to `"error {}", var`.
    pub fn expand_shorthand(&mut self, fields: &[Field]) {
        let raw_args = self.args.clone();
        let mut named_args = explicit_named_args.parse2(raw_args).unwrap();
        let mut member_index = Map::new();
        for (i, field) in fields.iter().enumerate() {
            member_index.insert(field.member.clone(), i);
        }

        let span = self.fmt.span();
        let fmt = self.fmt.value();
        let mut read = fmt.as_str();
        let mut out = String::new();
        let mut args = self.args.clone();
        let mut has_bonus_display = false;
        let mut implied_bounds = Set::new();

        let mut has_trailing_comma = false;
        if let Some(TokenTree::Punct(punct)) = args.clone().into_iter().last() {
            if punct.as_char() == ',' {
                has_trailing_comma = true;
            }
        }

        while let Some(brace) = read.find('{') {
            out += &read[..brace + 1];
            read = &read[brace + 1..];
            if read.starts_with('{') {
                out.push('{');
                read = &read[1..];
                continue;
            }
            let next = match read.chars().next() {
                Some(next) => next,
                None => return,
            };
            let member = match next {
                '0'..='9' => {
                    let int = take_int(&mut read);
                    let member = match int.parse::<u32>() {
                        Ok(index) => Member::Unnamed(Index { index, span }),
                        Err(_) => return,
                    };
                    if !member_index.contains_key(&member) {
                        out += ∫
                        continue;
                    }
                    member
                }
                'a'..='z' | 'A'..='Z' | '_' => {
                    let mut ident = take_ident(&mut read);
                    ident.set_span(span);
                    Member::Named(ident)
                }
                _ => continue,
            };
            if let Some(&field) = member_index.get(&member) {
                let end_spec = match read.find('}') {
                    Some(end_spec) => end_spec,
                    None => return,
                };
                let bound = match read[..end_spec].chars().next_back() {
                    Some('?') => Trait::Debug,
                    Some('o') => Trait::Octal,
                    Some('x') => Trait::LowerHex,
                    Some('X') => Trait::UpperHex,
                    Some('p') => Trait::Pointer,
                    Some('b') => Trait::Binary,
                    Some('e') => Trait::LowerExp,
                    Some('E') => Trait::UpperExp,
                    Some(_) | None => Trait::Display,
                };
                implied_bounds.insert((field, bound));
            }
            let local = match &member {
                Member::Unnamed(index) => format_ident!("_{}", index),
                Member::Named(ident) => ident.clone(),
            };
            let mut formatvar = local.clone();
            if formatvar.to_string().starts_with("r#") {
                formatvar = format_ident!("r_{}", formatvar);
            }
            if formatvar.to_string().starts_with('_') {
                // Work around leading underscore being rejected by 1.40 and
                // older compilers. https://github.com/rust-lang/rust/pull/66847
                formatvar = format_ident!("field_{}", formatvar);
            }
            out += &formatvar.to_string();
            if !named_args.insert(formatvar.clone()) {
                // Already specified in the format argument list.
                continue;
            }
            if !has_trailing_comma {
                args.extend(quote_spanned!(span=> ,));
            }
            args.extend(quote_spanned!(span=> #formatvar = #local));
            if read.starts_with('}') && member_index.contains_key(&member) {
                has_bonus_display = true;
                args.extend(quote_spanned!(span=> .as_display()));
            }
            has_trailing_comma = false;
        }

        out += read;
        self.fmt = LitStr::new(&out, self.fmt.span());
        self.args = args;
        self.has_bonus_display = has_bonus_display;
        self.implied_bounds = implied_bounds;
    }
}

fn explicit_named_args(input: ParseStream) -> Result<Set<Ident>> {
    let mut named_args = Set::new();

    while !input.is_empty() {
        if input.peek(Token![,]) && input.peek2(Ident::peek_any) && input.peek3(Token![=]) {
            input.parse::<Token![,]>()?;
            let ident = input.call(Ident::parse_any)?;
            input.parse::<Token![=]>()?;
            named_args.insert(ident);
        } else {
            input.parse::<TokenTree>()?;
        }
    }

    Ok(named_args)
}

fn take_int(read: &mut &str) -> String {
    let mut int = String::new();
    for (i, ch) in read.char_indices() {
        match ch {
            '0'..='9' => int.push(ch),
            _ => {
                *read = &read[i..];
                break;
            }
        }
    }
    int
}

fn take_ident(read: &mut &str) -> Ident {
    let mut ident = String::new();
    let raw = read.starts_with("r#");
    if raw {
        ident.push_str("r#");
        *read = &read[2..];
    }
    for (i, ch) in read.char_indices() {
        match ch {
            'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => ident.push(ch),
            _ => {
                *read = &read[i..];
                break;
            }
        }
    }
    Ident::parse_any.parse_str(&ident).unwrap()
}
<|endoftext|>


<commit_before>use core::rand::*;

#[deriving(Eq)]
pub struct Point {
    x : f64,
    y : f64
}

pub impl Point {
    fn dist(&self, other : &Point) -> f64 {
        f64::sqrt(f64::pow(self.x-other.x,2.0)+f64::pow(self.y-other.y,2.0))
    }
}
//
// * Génération aléatoire
//
impl Rand for Point {
    fn rand<R: Rng>(rng: &R) -> Point {
        Point { x: rng.gen::<f64>(), y: rng.gen::<f64>()}
    }
}

//
// * Opérateurs arithmétiques
//
// Addition
trait RhsOfAdd<Result> {
  fn add_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfAdd<Point> for Point {
  fn add_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (self.x+lhs.x), y:(self.y+lhs.y)}
   }
}
impl<Result, Rhs: RhsOfAdd<Result> > ops::Add<Rhs, Result> for Point {
  fn add(&self, rhs: &Rhs) -> Result {
    rhs.add_lhs_to(self)
  }
}
// Soustraction
trait RhsOfSub<Result> {
  fn sub_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfSub<Point> for Point {
  fn sub_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (-self.x+lhs.x), y:(-self.y+lhs.y)}
   }
}
impl<Result, Rhs: RhsOfSub<Result> > ops::Sub<Rhs, Result> for Point {
  fn sub(&self, rhs: &Rhs) -> Result {
    rhs.sub_lhs_to(self)
  }
}
// Multiplication
trait RhsOfMul<Result> {
  fn mul_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfMul<Point> for Point {
  fn mul_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (self.x*lhs.x), y:(self.y*lhs.y)}
   }
}
impl RhsOfMul<Point> for f64 {
  fn mul_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (self*lhs.x), y:(self*lhs.y)}
   }
}
impl<Result, Rhs: RhsOfMul<Result> > ops::Mul<Rhs, Result> for Point {
  fn mul(&self, rhs: &Rhs) -> Result {
    rhs.mul_lhs_to(self)
  }
}
// Division
trait RhsOfDiv<Result> {
  fn div_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfDiv<Point> for Point {
  fn div_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (lhs.x/self.x), y:(lhs.y/self.y)}
   }
}
impl RhsOfDiv<Point> for f64 {
  fn div_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (lhs.x/ *self), y:(lhs.y/ *self)}
   }
}
impl<Result, Rhs: RhsOfDiv<Result> > ops::Div<Rhs, Result> for Point {
  fn div(&self, rhs: &Rhs) -> Result {
    rhs.div_lhs_to(self)
  }
}

//
// * Test
//
#[test]
fn test_dist() {
    let pt1=@Point{ x: 1.0, y: 2.0};
    let pt2=@Point{ x: 2.0, y: 3.0};
    let distance=pt1.dist(pt2);

    assert!(distance==f64::sqrt(2.0));
}

#[test]
fn test_add() {
    let pt1=@Point{ x: 1.0, y: 2.0};
    let pt2=@Point{ x: -1.0, y: 3.0};
    let pt3=*pt1+*pt2;

    assert!((pt3.x==0.0)&&(pt3.y==5.0));
}

#[test]
fn test_sub() {
    let pt1=@Point{ x: 1.0, y: 2.0};
    let pt2=@Point{ x: -1.0, y: 3.0};
    let pt3=*pt1-*pt2;
    assert!((pt3.x==2.0)&&(pt3.y==-1.0));
}

#[test]
fn test_mult() {
    let pt1=@Point{ x: 1.0, y: 2.0};
    let pt2=@Point{ x: -1.0, y: 3.0};
    let pt3=(*pt1)*(*pt2);
    assert!((pt3.x==-1.0)&&(pt3.y==6.0));
    let pt4=(*pt1)*(2.0 as f64);
    assert!((pt4.x==2.0)&&(pt4.y==4.0));
}

#[test]
fn test_div() {
    let pt1=@Point{ x: 1.0, y: 2.0};
    let pt2=@Point{ x: -1.0, y: 3.0};
    let pt3=(*pt1)/(*pt2);
    assert!(pt3.dist(&Point{x:-1.0, y:2.0/3.0})==0.0);
    let pt4=(*pt1)/(2.0 as f64);
    assert!((pt4.x==0.5)&&(pt4.y==1.0));
}

#[test]
fn test_rand() {
    let pt1 : Point = rand::random();
    let pt2 : Point = rand::random();

    assert!(pt1 != pt2);
}
<commit_msg>Un constructeur (l'origine par défaut)<commit_after>use core::rand::*;

#[deriving(Eq)]
pub struct Point {
    x : f64,
    y : f64
}

pub impl Point {
    fn new() -> Point {
        Point{x:0.0, y:0.0}
    }

    fn dist(&self, other : &Point) -> f64 {
        f64::sqrt(f64::pow(self.x-other.x,2.0)+f64::pow(self.y-other.y,2.0))
    }
}
//
// * Génération aléatoire
//
impl Rand for Point {
    fn rand<R: Rng>(rng: &R) -> Point {
        Point { x: rng.gen::<f64>(), y: rng.gen::<f64>()}
    }
}

//
// * Opérateurs arithmétiques
//
// Addition
trait RhsOfAdd<Result> {
  fn add_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfAdd<Point> for Point {
  fn add_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (self.x+lhs.x), y:(self.y+lhs.y)}
   }
}
impl<Result, Rhs: RhsOfAdd<Result> > ops::Add<Rhs, Result> for Point {
  fn add(&self, rhs: &Rhs) -> Result {
    rhs.add_lhs_to(self)
  }
}
// Soustraction
trait RhsOfSub<Result> {
  fn sub_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfSub<Point> for Point {
  fn sub_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (-self.x+lhs.x), y:(-self.y+lhs.y)}
   }
}
impl<Result, Rhs: RhsOfSub<Result> > ops::Sub<Rhs, Result> for Point {
  fn sub(&self, rhs: &Rhs) -> Result {
    rhs.sub_lhs_to(self)
  }
}
// Multiplication
trait RhsOfMul<Result> {
  fn mul_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfMul<Point> for Point {
  fn mul_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (self.x*lhs.x), y:(self.y*lhs.y)}
   }
}
impl RhsOfMul<Point> for f64 {
  fn mul_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (self*lhs.x), y:(self*lhs.y)}
   }
}

impl<Result, Rhs: RhsOfMul<Result> > ops::Mul<Rhs, Result> for Point {
  fn mul(&self, rhs: &Rhs) -> Result {
    rhs.mul_lhs_to(self)
  }
}
// Division
trait RhsOfDiv<Result> {
  fn div_lhs_to(&self, lhs: &Point) -> Result;
}
impl RhsOfDiv<Point> for Point {
  fn div_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (lhs.x/self.x), y:(lhs.y/self.y)}
   }
}
impl RhsOfDiv<Point> for f64 {
  fn div_lhs_to(&self, lhs: &Point) -> Point {
    Point{x: (lhs.x/ *self), y:(lhs.y/ *self)}
   }
}
impl<Result, Rhs: RhsOfDiv<Result> > ops::Div<Rhs, Result> for Point {
  fn div(&self, rhs: &Rhs) -> Result {
    rhs.div_lhs_to(self)
  }
}

//
// * Test
//
#[test]
fn test_dist() {
    let pt1=@Point{ x: 1.0, y: 2.0};
    let pt2=@Point{ x: 2.0, y: 3.0};
    let distance=pt1.dist(pt2);

    assert!(distance==f64::sqrt(2.0));
}

#[test]
fn test_add() {
    let pt1=@Point{ x: 1.0, y: 2.0};
    let pt2=@Point{ x: -1.0, y: 3.0};
    let pt3=*pt1+*pt2;

    assert!((pt3.x==0.0)&&(pt3.y==5.0));
}

#[test]
fn test_sub() {
    let pt1=@Point{ x: 1.0, y: 2.0};
    let pt2=@Point{ x: -1.0, y: 3.0};
    let pt3=*pt1-*pt2;
    assert!((pt3.x==2.0)&&(pt3.y==-1.0));
}

#[test]
fn test_mult() {
    let pt1=@Point{ x: 1.0, y: 2.0};
    let pt2=@Point{ x: -1.0, y: 3.0};
    let pt3=(*pt1)*(*pt2);
    assert!((pt3.x==-1.0)&&(pt3.y==6.0));
    let pt4=(*pt1)*(2.0 as f64);
    assert!((pt4.x==2.0)&&(pt4.y==4.0));
}

#[test]
fn test_div() {
    let pt1=@Point{ x: 1.0, y: 2.0};
    let pt2=@Point{ x: -1.0, y: 3.0};
    let pt3=(*pt1)/(*pt2);
    assert!(pt3.dist(&Point{x:-1.0, y:2.0/3.0})==0.0);
    let pt4=(*pt1)/(2.0 as f64);
    assert!((pt4.x==0.5)&&(pt4.y==1.0));
}

#[test]
fn test_rand() {
    let pt1 : Point = rand::random();
    let pt2 : Point = rand::random();

    assert!(pt1 != pt2);
}
<|endoftext|>


<commit_before>#[derive(Clone, Debug)]
/// Expression enum.
pub enum Expression {
    Unary(UnaryExpr),
    Binary(BinaryExpr),
    Literal(Literal),
    Identifier(Identifier),
    FunctionCall(Call),
    Sub(Sub),
    Cast(Cast),
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
/// Unary Operators
pub enum UnaryOperator {
    Not,
    Negative,
    BitwiseNot,
}

#[derive(Debug, Clone)]
/// Unary Expression.
pub struct UnaryExpr {
    pub operator: UnaryOperator,
    pub right: Box<Expression>,
}

#[derive(Copy, Clone, Debug)]
/// Enum representing binary operators.
pub enum BinaryOperator {
    Arithmetic(ArithmeticOperator),
    Logical(LogicalOperator),
    Relational(RelationalOperator),
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
/// Arithmetic Operators
pub enum ArithmeticOperator {
    Add,
    Subtract,
    Multiply,
    Divide,
    Modulo,
    BitwiseAnd,
    BitwiseOr,
    BitwiseXor,
    LeftShift,
    RightShift,
    Increment,
    Decrement,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
/// Logical Operators
pub enum LogicalOperator {
    And,
    Or,
    Xor,
    ShortAnd,
    ShortOr,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
/// Relational Operators
pub enum RelationalOperator {
    Equal,
    NotEqual,
    GreaterThan,
    LessThan,
    GreaterOrEqual,
    LessOrEqual,
}

#[derive(Debug, Clone)]
/// Binary Expression.
pub struct BinaryExpr {
    pub left: Box<Expression>,
    pub operator: BinaryOperator,
    pub right: Box<Expression>,
}

#[derive(Debug, Clone)]
/// Subfield access expression. (i.e. "left.right")
pub struct Sub {
    pub left: Box<Expression>,
    pub right: Box<Expression>,
}

#[derive(Debug, Clone)]
/// Cast expression struct (i.e. "value to type")
pub struct Cast {
    pub value: Box<Expression>,
    pub to_type: Type,
}

#[derive(Debug, Clone)]
/// Literal struct.
pub struct Literal {
    pub literal: String,
}

#[derive(Debug, Clone)]
/// Identifier struct.
pub struct Identifier {
    pub id: String,
}

#[derive(Debug, Clone)]
/// Type struct.
pub struct Type {
    pub id: String,
    pub type_parameters: Vec<Type>,
}

#[derive(Debug, Clone)]
/// Function call.
pub struct Call {
    pub callee: Identifier,
    pub args: Vec<Box<Expression>>,
}

#[derive(Debug, Clone)]
/// Enum for statements.
pub enum Statement {
    Block(Block),
    Expression(Expression),
    Assignment(Assignment),
    WhileLoop(WhileLoop),
    ForLoop(ForLoop),
    FnDef(FunctionDefinition),
    ClassDef(ClassDeclaration),
    TraitDef(TraitDeclaration),
    EnumDef(EnumDeclaration),
    ConstDef(Constant),
    Return(Return),
    Break(Break),
    Continue(Continue),
    SingleCondition(Condition),
    Conditional(Conditional),
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
/// Different types of assignments, one for mutability, the other for immutability.
pub enum Assigner {
    Let,
    Var,
}

#[derive(Debug, Clone)]
/// Assignment statement.
pub struct Assignment {
    pub left: Identifier,
    pub assign_type: Assigner,
    pub right: Box<Expression>,
    pub declared_type: Option<Type>,
}

#[derive(Debug, Clone)]
/// Block of statements
pub struct Block {
    pub statements: Vec<Box<Statement>>,
}

#[derive(Debug, Clone)]
/// Single conditional statement.
pub struct Condition {
    pub condition: Expression,
    pub block: Block,
}

#[derive(Debug, Clone)]
/// Conditional block
pub struct Conditional {
    pub conditions: Vec<Condition>,
}

#[derive(Debug, Clone)]
/// While loop struct.
pub struct WhileLoop {
    pub id: LoopAnnotation,
    pub condition: Expression,
    pub block: Block,
}

#[derive(Debug, Clone)]
/// For loop struct.
pub struct ForLoop {
    pub id: LoopAnnotation,
    pub assignment: Expression,
    pub source_var: Expression,
    pub block: Block,
}

#[derive(Debug, Clone)]
/// Function defining struct.
pub struct FunctionDefinition {
    pub declared_type: Option<Type>,
    pub id: Identifier,
    pub args: Vec<(Identifier, Option<Type>)>, //(name, type)
    pub block: Block,
}

#[derive(Debug, Clone)]
/// Class declaration struct.
pub struct ClassDeclaration {
    pub generics: Vec<Type>,
    pub id: Identifier,
    pub traits_implemented: Vec<Identifier>,
    pub fields: Vec<(Identifier, Type)>,
}

#[derive(Debug, Clone)]
/// Class declaration struct.
pub struct TraitDeclaration {
    pub generics: Vec<Type>,
    pub id: Identifier,
    pub requires: Vec<Identifier>,
    pub block: Block,
}

#[derive(Debug, Clone)]
/// Class declaration struct.
pub struct EnumDeclaration {
    pub generics: Vec<Type>,
    pub id: Identifier,
    pub variants: Vec<ClassDeclaration>,
}

#[derive(Debug, Clone)]
/// Constant struct.
pub struct Constant {
    pub id: Identifier,
    pub declared_type: Option<Type>,
    pub val: Box<Expression>,
}

#[derive(Debug, Clone)]
/// Return statement struct.
pub struct Return {
    pub val: Box<Expression>
}

#[derive(Debug, Clone)]
/// Loop annotation struct
pub struct LoopAnnotation {
    pub id: String,
}

#[derive(Debug, Clone)]
/// Break statement struct.
pub struct Break {
    pub id: LoopAnnotation,
}

#[derive(Debug, Clone)]
/// Continue statement struct.
pub struct Continue {
    pub id: LoopAnnotation,
}

#[derive(Debug, Clone)]
/// Module struct
/// Module is not in `Statement` because
/// users should not be able to define modules in a file.
/// Each Wright file should be it's own independent Module.
pub struct Module {
    pub id: Identifier,
    pub content: Block,
}

impl Module {
    pub fn new(name: String) -> Self {
        Module {
            id: Identifier{id: name},
            content: Block{statements: vec![]}
        }
    }
}

<commit_msg>Docs Fix<commit_after>#[derive(Clone, Debug)]
/// Expression enum.
pub enum Expression {
    Unary(UnaryExpr),
    Binary(BinaryExpr),
    Literal(Literal),
    Identifier(Identifier),
    FunctionCall(Call),
    Sub(Sub),
    Cast(Cast),
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
/// Unary Operators
pub enum UnaryOperator {
    Not,
    Negative,
    BitwiseNot,
}

#[derive(Debug, Clone)]
/// Unary Expression.
pub struct UnaryExpr {
    pub operator: UnaryOperator,
    pub right: Box<Expression>,
}

#[derive(Copy, Clone, Debug)]
/// Enum representing binary operators.
pub enum BinaryOperator {
    Arithmetic(ArithmeticOperator),
    Logical(LogicalOperator),
    Relational(RelationalOperator),
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
/// Arithmetic Operators
pub enum ArithmeticOperator {
    Add,
    Subtract,
    Multiply,
    Divide,
    Modulo,
    BitwiseAnd,
    BitwiseOr,
    BitwiseXor,
    LeftShift,
    RightShift,
    Increment,
    Decrement,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
/// Logical Operators
pub enum LogicalOperator {
    And,
    Or,
    Xor,
    ShortAnd,
    ShortOr,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
/// Relational Operators
pub enum RelationalOperator {
    Equal,
    NotEqual,
    GreaterThan,
    LessThan,
    GreaterOrEqual,
    LessOrEqual,
}

#[derive(Debug, Clone)]
/// Binary Expression.
pub struct BinaryExpr {
    pub left: Box<Expression>,
    pub operator: BinaryOperator,
    pub right: Box<Expression>,
}

#[derive(Debug, Clone)]
/// Subfield access expression. (i.e. "left.right")
pub struct Sub {
    pub left: Box<Expression>,
    pub right: Box<Expression>,
}

#[derive(Debug, Clone)]
/// Cast expression struct (i.e. "value to type")
pub struct Cast {
    pub value: Box<Expression>,
    pub to_type: Type,
}

#[derive(Debug, Clone)]
/// Literal struct.
pub struct Literal {
    pub literal: String,
}

#[derive(Debug, Clone)]
/// Identifier struct.
pub struct Identifier {
    pub id: String,
}

#[derive(Debug, Clone)]
/// Type struct.
pub struct Type {
    pub id: String,
    pub type_parameters: Vec<Type>,
}

#[derive(Debug, Clone)]
/// Function call.
pub struct Call {
    pub callee: Identifier,
    pub args: Vec<Box<Expression>>,
}

#[derive(Debug, Clone)]
/// Enum for statements.
pub enum Statement {
    Block(Block),
    Expression(Expression),
    Assignment(Assignment),
    WhileLoop(WhileLoop),
    ForLoop(ForLoop),
    FnDef(FunctionDefinition),
    ClassDef(ClassDeclaration),
    TraitDef(TraitDeclaration),
    EnumDef(EnumDeclaration),
    ConstDef(Constant),
    Return(Return),
    Break(Break),
    Continue(Continue),
    SingleCondition(Condition),
    Conditional(Conditional),
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
/// Different types of assignments, one for mutability, the other for immutability.
pub enum Assigner {
    Let,
    Var,
}

#[derive(Debug, Clone)]
/// Assignment statement.
pub struct Assignment {
    pub left: Identifier,
    pub assign_type: Assigner,
    pub right: Box<Expression>,
    pub declared_type: Option<Type>,
}

#[derive(Debug, Clone)]
/// Block of statements
pub struct Block {
    pub statements: Vec<Box<Statement>>,
}

#[derive(Debug, Clone)]
/// Single conditional statement.
pub struct Condition {
    pub condition: Expression,
    pub block: Block,
}

#[derive(Debug, Clone)]
/// Conditional block
pub struct Conditional {
    pub conditions: Vec<Condition>,
}

#[derive(Debug, Clone)]
/// While loop struct.
pub struct WhileLoop {
    pub id: LoopAnnotation,
    pub condition: Expression,
    pub block: Block,
}

#[derive(Debug, Clone)]
/// For loop struct.
pub struct ForLoop {
    pub id: LoopAnnotation,
    pub assignment: Expression,
    pub source_var: Expression,
    pub block: Block,
}

#[derive(Debug, Clone)]
/// Function defining struct.
pub struct FunctionDefinition {
    pub declared_type: Option<Type>,
    pub id: Identifier,
    pub args: Vec<(Identifier, Option<Type>)>, //(name, type)
    pub block: Block,
}

#[derive(Debug, Clone)]
/// Class declaration struct.
pub struct ClassDeclaration {
    pub generics: Vec<Type>,
    pub id: Identifier,
    pub traits_implemented: Vec<Identifier>,
    pub fields: Vec<(Identifier, Type)>,
}

#[derive(Debug, Clone)]
/// Trait declaration struct.
pub struct TraitDeclaration {
    pub generics: Vec<Type>,
    pub id: Identifier,
    pub requires: Vec<Identifier>,
    pub block: Block,
}

#[derive(Debug, Clone)]
/// Enum (tagged union) declaration struct.
pub struct EnumDeclaration {
    pub generics: Vec<Type>,
    pub id: Identifier,
    pub variants: Vec<ClassDeclaration>,
}

#[derive(Debug, Clone)]
/// Constant struct.
pub struct Constant {
    pub id: Identifier,
    pub declared_type: Option<Type>,
    pub val: Box<Expression>,
}

#[derive(Debug, Clone)]
/// Return statement struct.
pub struct Return {
    pub val: Box<Expression>
}

#[derive(Debug, Clone)]
/// Loop annotation struct
pub struct LoopAnnotation {
    pub id: String,
}

#[derive(Debug, Clone)]
/// Break statement struct.
pub struct Break {
    pub id: LoopAnnotation,
}

#[derive(Debug, Clone)]
/// Continue statement struct.
pub struct Continue {
    pub id: LoopAnnotation,
}

#[derive(Debug, Clone)]
/// Module struct
/// Module is not in `Statement` because
/// users should not be able to define modules in a file.
/// Each Wright file should be it's own independent Module.
pub struct Module {
    pub id: Identifier,
    pub content: Block,
}

impl Module {
    pub fn new(name: String) -> Self {
        Module {
            id: Identifier{id: name},
            content: Block{statements: vec![]}
        }
    }
}

<|endoftext|>