<commit_before>#![feature(unboxed_closures)]
#![feature(plugin)]
#![feature(box_syntax)]
#![feature(std_misc, collections, path_ext)]
#[macro_use]
#[macro_use]
extern crate wtftw;
extern crate wtftw_contrib;

use std::fs::PathExt;
use std::io::Write;
use std::path::Path;
use std::env;
use std::ops::Deref;
//use std::ffi::AsOsStr;
use wtftw::window_system::*;
use wtftw::window_manager::*;
use wtftw::handlers::default::*;
use wtftw::config::*;
use wtftw::util::*;
use wtftw::layout::Direction;
use wtftw::layout::LayoutMessage;
use wtftw_contrib::layout::{ AvoidStrutsLayout, LayoutCollection, BinarySpacePartition, GapLayout, MirrorLayout, NoBordersLayout, FullLayout };

#[no_mangle]
pub extern fn configure(_: &mut WindowManager, w: &WindowSystem, config: &mut Config) {
    let modm = MOD1MASK;

    config.general.mod_mask = modm;
    config.general.border_color = 0x404040;
    config.general.focus_border_color = 0xebebeb;
    config.general.border_width = 1;
    config.general.terminal = (String::from("xterm"), String::from(""));
    config.general.layout = LayoutCollection::new(vec!(
            GapLayout::new(0, AvoidStrutsLayout::new(vec!(Direction::Up, Direction::Down), BinarySpacePartition::new())),
            GapLayout::new(0, AvoidStrutsLayout::new(vec!(Direction::Up, Direction::Down), MirrorLayout::new(BinarySpacePartition::new()))),
            NoBordersLayout::new(box FullLayout)));

    config.general.tags = (vec!("一: ターミナル", "二: ウェブ", "三: コード",
                                "四: メディア", "五: スチーム", "六: ラテック",
                                "七: 音楽", "八: im", "九: 残り"))
        .into_iter().map(String::from).collect();

    // Register key handlers

    // Some standard key handlers for starting, restarting, etc.
    add_key_handler_str!(config, w, "q",      modm | SHIFTMASK, exit);
    add_key_handler_str!(config, w, "q",      modm,             restart);
    add_key_handler_str!(config, w, "Return", modm | SHIFTMASK, start_terminal);
    add_key_handler_str!(config, w, "p",      modm,             start_launcher);

    // Focus and window movement
    add_key_handler_str!(config, w, "j", modm,             |m, w, c| m.windows(w.deref(), c, &|x| x.focus_down()));
    add_key_handler_str!(config, w, "k", modm,             |m, w, c| m.windows(w.deref(), c, &|x| x.focus_up()));
    add_key_handler_str!(config, w, "j", modm | SHIFTMASK, |m, w, c| m.windows(w.deref(), c, &|x| x.swap_down()));
    add_key_handler_str!(config, w, "k", modm | SHIFTMASK, |m, w, c| m.windows(w.deref(), c, &|x| x.swap_up()));
    add_key_handler_str!(config, w, "Return", modm,        |m, w, c| m.windows(w.deref(), c, &|x| x.swap_master()));
    add_key_handler_str!(config, w, "c", modm, |m, w, c| m.kill_window(w.deref()).windows(w.deref(), c, &|x| x.clone()));

    add_key_handler_str!(config, w, "t", modm, |m, w, c| {
        match m.workspaces.peek() {
            Some(window) => m.windows(w.deref(), c, &|x| x.sink(window)),
            None => m.clone()
        }
    });

    // Layout messages
    add_key_handler_str!(config, w, "h",      modm,             send_layout_message!(LayoutMessage::Decrease));
    add_key_handler_str!(config, w, "l",      modm,             send_layout_message!(LayoutMessage::Increase));
    add_key_handler_str!(config, w, "z",      modm,             send_layout_message!(LayoutMessage::DecreaseSlave));
    add_key_handler_str!(config, w, "a",      modm,             send_layout_message!(LayoutMessage::IncreaseSlave));
    add_key_handler_str!(config, w, "x",      modm | SHIFTMASK, send_layout_message!(LayoutMessage::IncreaseGap));
    add_key_handler_str!(config, w, "s",      modm | SHIFTMASK, send_layout_message!(LayoutMessage::DecreaseGap));
    add_key_handler_str!(config, w, "comma",  modm,             send_layout_message!(LayoutMessage::IncreaseMaster));
    add_key_handler_str!(config, w, "period", modm,             send_layout_message!(LayoutMessage::DecreaseMaster));
    add_key_handler_str!(config, w, "space",  modm,             send_layout_message!(LayoutMessage::Next));
    add_key_handler_str!(config, w, "space",  modm | SHIFTMASK, send_layout_message!(LayoutMessage::Prev));
    add_key_handler_str!(config, w, "r",      modm,             send_layout_message!(LayoutMessage::TreeRotate));
    add_key_handler_str!(config, w, "s",      modm,             send_layout_message!(LayoutMessage::TreeSwap));
    add_key_handler_str!(config, w, "u",      modm | SHIFTMASK, send_layout_message!(LayoutMessage::TreeExpandTowards(Direction::Left)));
    add_key_handler_str!(config, w, "p",      modm | SHIFTMASK, send_layout_message!(LayoutMessage::TreeExpandTowards(Direction::Right)));
    add_key_handler_str!(config, w, "i",      modm | SHIFTMASK, send_layout_message!(LayoutMessage::TreeExpandTowards(Direction::Down)));
    add_key_handler_str!(config, w, "o",      modm | SHIFTMASK, send_layout_message!(LayoutMessage::TreeExpandTowards(Direction::Up)));
    add_key_handler_str!(config, w, "u",      modm | CONTROLMASK, send_layout_message!(LayoutMessage::TreeShrinkFrom(Direction::Left)));
    add_key_handler_str!(config, w, "p",      modm | CONTROLMASK, send_layout_message!(LayoutMessage::TreeShrinkFrom(Direction::Right)));
    add_key_handler_str!(config, w, "i",      modm | CONTROLMASK, send_layout_message!(LayoutMessage::TreeShrinkFrom(Direction::Down)));
    add_key_handler_str!(config, w, "o",      modm | CONTROLMASK, send_layout_message!(LayoutMessage::TreeShrinkFrom(Direction::Up)));

    // Workspace switching and moving
    for i in (1usize..10) {
        add_key_handler_str!(config, w, &i.to_string(), modm,
        move |m, w, c| switch_to_workspace(m, w, c, i - 1));

        add_key_handler_str!(config, w, &i.to_string(), modm | SHIFTMASK,
        move |m, w, c| move_window_to_workspace(m, w, c, i - 1));
    }

    // Media keys
    add_key_handler_str!(config, w, "j", modm | CONTROLMASK, run!("amixer", "-q set Master 5%-"));
    add_key_handler_str!(config, w, "k", modm | CONTROLMASK, run!("amixer", "-q set Master 5%+"));

    add_key_handler_code!(config, 0x1008ff11, NONEMASK, run!("amixer", "-q set Master 5%-"));
    add_key_handler_code!(config, 0x1008ff13, NONEMASK, run!("amixer", "-q set Master 5%+"));

    add_key_handler_code!(config, 0x1008ff02, NONEMASK, run!("xbacklight", "+10"));
    add_key_handler_code!(config, 0x1008ff03, NONEMASK, run!("xbacklight", "-10"));

    add_mouse_handler!(config, BUTTON1, modm,
                       |m, w, c, s| {
                           m.focus(s, w.deref(), c).mouse_move_window(w.deref(), c, s).windows(w.deref(), c, &|x| x.shift_master())
                       });
    add_mouse_handler!(config, BUTTON3, modm,
                       |m, w, c, s| {
                           m.focus(s, w.deref(), c).mouse_resize_window(w.deref(), c, s).windows(w.deref(), c, &|x| x.shift_master())
                       });

    // Xmobar handling and formatting
    let home_dir = env::home_dir().unwrap();
    let home = home_dir.as_os_str().to_str().unwrap();
    let xmobar_config = format!("{}/.xmonad/xmobar1.hs", home);

    if Path::new(&xmobar_config.clone()).is_file() {
        let mut xmobar = spawn_pipe(config, "/home/rootnode/.cabal/bin/xmobar",
                                    vec!(xmobar_config));
        let tags = config.general.tags.clone();
        config.set_log_hook(box move |m, w| {
            let p = &mut xmobar;
            let tags = &tags;
            let workspaces = tags.clone().iter()
                .enumerate()
                .map(|(i, _)| if i as u32 == m.workspaces.current.workspace.id {
                    format!("<fc=#fb4934>■</fc>")
                } else if m.workspaces.visible.iter().any(|w| w.workspace.id == i as u32) {
                    format!("<fc=#fabd2f>■</fc>")
                } else {
                    format!("■")
                })
            .fold(String::from(""), |a, x| {
                let mut r = a.clone();
                r.push_str(&x);
                r
            });

            let name = match m.workspaces.peek() {
                None => String::from(""),
                Some(window) => w.get_window_name(window)
            };
            let content = format!("{} {} {}\n", workspaces, m.workspaces.current.workspace.layout.description(), name);
            match p.write().unwrap().stdin.as_mut() {
                Some(pin) => {
                    match pin.write(content.as_bytes()) {
                        _      => ()
                    };
                    pin.flush().unwrap();
                },
                _ => ()
            }
        });
    };
}
<commit_msg>Config without unstable features<commit_after>#[macro_use]
#[macro_use]
extern crate wtftw;
extern crate wtftw_contrib;

use std::io::Write;
use std::fs::metadata;
use std::env;
use std::ops::Deref;
//use std::ffi::AsOsStr;
use wtftw::window_system::*;
use wtftw::window_manager::*;
use wtftw::handlers::default::*;
use wtftw::config::*;
use wtftw::util::*;
use wtftw::layout::Direction;
use wtftw::layout::LayoutMessage;
use wtftw_contrib::layout::{ AvoidStrutsLayout, LayoutCollection, BinarySpacePartition, GapLayout, MirrorLayout, NoBordersLayout, FullLayout };

#[no_mangle]
pub extern fn configure(_: &mut WindowManager, w: &WindowSystem, config: &mut Config) {
    let modm = MOD1MASK;

    config.general.mod_mask = modm;
    config.general.border_color = 0x404040;
    config.general.focus_border_color = 0xebebeb;
    config.general.border_width = 1;
    config.general.terminal = (String::from("xterm"), String::from(""));
    config.general.layout = LayoutCollection::new(vec!(
            GapLayout::new(0, AvoidStrutsLayout::new(vec!(Direction::Up, Direction::Down), BinarySpacePartition::new())),
            GapLayout::new(0, AvoidStrutsLayout::new(vec!(Direction::Up, Direction::Down), MirrorLayout::new(BinarySpacePartition::new()))),
            NoBordersLayout::new(Box::new(FullLayout))));

    config.general.tags = (vec!("一: ターミナル", "二: ウェブ", "三: コード",
                                "四: メディア", "五: スチーム", "六: ラテック",
                                "七: 音楽", "八: im", "九: 残り"))
        .into_iter().map(String::from).collect();

    // Register key handlers

    // Some standard key handlers for starting, restarting, etc.
    add_key_handler_str!(config, w, "q",      modm | SHIFTMASK, exit);
    add_key_handler_str!(config, w, "q",      modm,             restart);
    add_key_handler_str!(config, w, "Return", modm | SHIFTMASK, start_terminal);
    add_key_handler_str!(config, w, "p",      modm,             start_launcher);

    // Focus and window movement
    add_key_handler_str!(config, w, "j", modm,             |m, w, c| m.windows(w.deref(), c, &|x| x.focus_down()));
    add_key_handler_str!(config, w, "k", modm,             |m, w, c| m.windows(w.deref(), c, &|x| x.focus_up()));
    add_key_handler_str!(config, w, "j", modm | SHIFTMASK, |m, w, c| m.windows(w.deref(), c, &|x| x.swap_down()));
    add_key_handler_str!(config, w, "k", modm | SHIFTMASK, |m, w, c| m.windows(w.deref(), c, &|x| x.swap_up()));
    add_key_handler_str!(config, w, "Return", modm,        |m, w, c| m.windows(w.deref(), c, &|x| x.swap_master()));
    add_key_handler_str!(config, w, "c", modm, |m, w, c| m.kill_window(w.deref()).windows(w.deref(), c, &|x| x.clone()));

    add_key_handler_str!(config, w, "t", modm, |m, w, c| {
        match m.workspaces.peek() {
            Some(window) => m.windows(w.deref(), c, &|x| x.sink(window)),
            None => m.clone()
        }
    });

    // Layout messages
    add_key_handler_str!(config, w, "h",      modm,             send_layout_message!(LayoutMessage::Decrease));
    add_key_handler_str!(config, w, "l",      modm,             send_layout_message!(LayoutMessage::Increase));
    add_key_handler_str!(config, w, "z",      modm,             send_layout_message!(LayoutMessage::DecreaseSlave));
    add_key_handler_str!(config, w, "a",      modm,             send_layout_message!(LayoutMessage::IncreaseSlave));
    add_key_handler_str!(config, w, "x",      modm | SHIFTMASK, send_layout_message!(LayoutMessage::IncreaseGap));
    add_key_handler_str!(config, w, "s",      modm | SHIFTMASK, send_layout_message!(LayoutMessage::DecreaseGap));
    add_key_handler_str!(config, w, "comma",  modm,             send_layout_message!(LayoutMessage::IncreaseMaster));
    add_key_handler_str!(config, w, "period", modm,             send_layout_message!(LayoutMessage::DecreaseMaster));
    add_key_handler_str!(config, w, "space",  modm,             send_layout_message!(LayoutMessage::Next));
    add_key_handler_str!(config, w, "space",  modm | SHIFTMASK, send_layout_message!(LayoutMessage::Prev));
    add_key_handler_str!(config, w, "r",      modm,             send_layout_message!(LayoutMessage::TreeRotate));
    add_key_handler_str!(config, w, "s",      modm,             send_layout_message!(LayoutMessage::TreeSwap));
    add_key_handler_str!(config, w, "u",      modm | SHIFTMASK, send_layout_message!(LayoutMessage::TreeExpandTowards(Direction::Left)));
    add_key_handler_str!(config, w, "p",      modm | SHIFTMASK, send_layout_message!(LayoutMessage::TreeExpandTowards(Direction::Right)));
    add_key_handler_str!(config, w, "i",      modm | SHIFTMASK, send_layout_message!(LayoutMessage::TreeExpandTowards(Direction::Down)));
    add_key_handler_str!(config, w, "o",      modm | SHIFTMASK, send_layout_message!(LayoutMessage::TreeExpandTowards(Direction::Up)));
    add_key_handler_str!(config, w, "u",      modm | CONTROLMASK, send_layout_message!(LayoutMessage::TreeShrinkFrom(Direction::Left)));
    add_key_handler_str!(config, w, "p",      modm | CONTROLMASK, send_layout_message!(LayoutMessage::TreeShrinkFrom(Direction::Right)));
    add_key_handler_str!(config, w, "i",      modm | CONTROLMASK, send_layout_message!(LayoutMessage::TreeShrinkFrom(Direction::Down)));
    add_key_handler_str!(config, w, "o",      modm | CONTROLMASK, send_layout_message!(LayoutMessage::TreeShrinkFrom(Direction::Up)));

    // Workspace switching and moving
    for i in (1usize..10) {
        add_key_handler_str!(config, w, &i.to_string(), modm,
        move |m, w, c| switch_to_workspace(m, w, c, i - 1));

        add_key_handler_str!(config, w, &i.to_string(), modm | SHIFTMASK,
        move |m, w, c| move_window_to_workspace(m, w, c, i - 1));
    }

    // Media keys
    add_key_handler_str!(config, w, "j", modm | CONTROLMASK, run!("amixer", "-q set Master 5%-"));
    add_key_handler_str!(config, w, "k", modm | CONTROLMASK, run!("amixer", "-q set Master 5%+"));

    add_key_handler_code!(config, 0x1008ff11, NONEMASK, run!("amixer", "-q set Master 5%-"));
    add_key_handler_code!(config, 0x1008ff13, NONEMASK, run!("amixer", "-q set Master 5%+"));

    add_key_handler_code!(config, 0x1008ff02, NONEMASK, run!("xbacklight", "+10"));
    add_key_handler_code!(config, 0x1008ff03, NONEMASK, run!("xbacklight", "-10"));

    add_mouse_handler!(config, BUTTON1, modm,
                       |m, w, c, s| {
                           m.focus(s, w.deref(), c).mouse_move_window(w.deref(), c, s).windows(w.deref(), c, &|x| x.shift_master())
                       });
    add_mouse_handler!(config, BUTTON3, modm,
                       |m, w, c, s| {
                           m.focus(s, w.deref(), c).mouse_resize_window(w.deref(), c, s).windows(w.deref(), c, &|x| x.shift_master())
                       });

    // Xmobar handling and formatting
    let home_dir = env::home_dir().unwrap();
    let home = home_dir.as_os_str().to_str().unwrap();
    let xmobar_config = format!("{}/.xmonad/xmobar1.hs", home);

    if metadata(&xmobar_config).map(|s| s.is_file()).unwrap_or(false) {
        let mut xmobar = spawn_pipe(config, "/home/rootnode/.cabal/bin/xmobar",
                                    vec!(xmobar_config));
        let tags = config.general.tags.clone();
        config.set_log_hook(Box::new(move |m, w| {
            let p = &mut xmobar;
            let tags = &tags;
            let workspaces = tags.clone().iter()
                .enumerate()
                .map(|(i, _)| if i as u32 == m.workspaces.current.workspace.id {
                    format!("<fc=#fb4934>■</fc>")
                } else if m.workspaces.visible.iter().any(|w| w.workspace.id == i as u32) {
                    format!("<fc=#fabd2f>■</fc>")
                } else {
                    format!("■")
                })
            .fold(String::from(""), |a, x| {
                let mut r = a.clone();
                r.push_str(&x);
                r
            });

            let name = match m.workspaces.peek() {
                None => String::from(""),
                Some(window) => w.get_window_name(window)
            };
            let content = format!("{} {} {}\n", workspaces, m.workspaces.current.workspace.layout.description(), name);
            match p.write().unwrap().stdin.as_mut() {
                Some(pin) => {
                    match pin.write(content.as_bytes()) {
                        _      => ()
                    };
                    pin.flush().unwrap();
                },
                _ => ()
            }
        }));
    };
}
<|endoftext|>


<commit_before>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use std::sync::atomic::{AtomicI32, Ordering};
use std::time::Instant;
use libc;

#[cfg(target_arch = "x86")]
const SYS_FUTEX: libc::c_long = 240;
#[cfg(target_arch = "x86_64")]
const SYS_FUTEX: libc::c_long = 202;
#[cfg(target_arch = "arm")]
const SYS_FUTEX: libc::c_long = 240;
#[cfg(target_arch = "aarch64")]
const SYS_FUTEX: libc::c_long = 98;

const FUTEX_WAIT: i32 = 0;
const FUTEX_WAKE: i32 = 1;
const FUTEX_PRIVATE: i32 = 128;

// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
    futex: AtomicI32,
}

impl ThreadParker {
    pub fn new() -> ThreadParker {
        ThreadParker {
            futex: AtomicI32::new(0),
        }
    }

    // Prepares the parker. This should be called before adding it to the queue.
    pub unsafe fn prepare_park(&self) {
        self.futex.store(1, Ordering::Relaxed);
    }

    // Checks if the park timed out. This should be called while holding the
    // queue lock after park_until has returned false.
    pub unsafe fn timed_out(&self) -> bool {
        self.futex.load(Ordering::Relaxed) != 0
    }

    // Parks the thread until it is unparked. This should be called after it has
    // been added to the queue, after unlocking the queue.
    pub unsafe fn park(&self) {
        while self.futex.load(Ordering::Acquire) != 0 {
            let r = libc::syscall(SYS_FUTEX, &self.futex, FUTEX_WAIT | FUTEX_PRIVATE, 1, 0);
            debug_assert!(r == 0 || r == -1);
            if r == -1 {
                debug_assert!(
                    *libc::__errno_location() == libc::EINTR
                        || *libc::__errno_location() == libc::EAGAIN
                );
            }
        }
    }

    // Parks the thread until it is unparked or the timeout is reached. This
    // should be called after it has been added to the queue, after unlocking
    // the queue. Returns true if we were unparked and false if we timed out.
    pub unsafe fn park_until(&self, timeout: Instant) -> bool {
        while self.futex.load(Ordering::Acquire) != 0 {
            let now = Instant::now();
            if timeout <= now {
                return false;
            }
            let diff = timeout - now;
            if diff.as_secs() as libc::time_t as u64 != diff.as_secs() {
                // Timeout overflowed, just sleep indefinitely
                self.park();
                return true;
            }
            let ts = libc::timespec {
                tv_sec: diff.as_secs() as libc::time_t,
                tv_nsec: diff.subsec_nanos() as libc::c_long,
            };
            let r = libc::syscall(SYS_FUTEX, &self.futex, FUTEX_WAIT | FUTEX_PRIVATE, 1, &ts);
            debug_assert!(r == 0 || r == -1);
            if r == -1 {
                debug_assert!(
                    *libc::__errno_location() == libc::EINTR
                        || *libc::__errno_location() == libc::EAGAIN
                        || *libc::__errno_location() == libc::ETIMEDOUT
                );
            }
        }
        true
    }

    // Locks the parker to prevent the target thread from exiting. This is
    // necessary to ensure that thread-local ThreadData objects remain valid.
    // This should be called while holding the queue lock.
    pub unsafe fn unpark_lock(&self) -> UnparkHandle {
        // We don't need to lock anything, just clear the state
        self.futex.store(0, Ordering::Release);

        UnparkHandle { futex: &self.futex }
    }
}

// Handle for a thread that is about to be unparked. We need to mark the thread
// as unparked while holding the queue lock, but we delay the actual unparking
// until after the queue lock is released.
pub struct UnparkHandle {
    futex: *const AtomicI32,
}

impl UnparkHandle {
    // Wakes up the parked thread. This should be called after the queue lock is
    // released to avoid blocking the queue for too long.
    pub unsafe fn unpark(self) {
        // The thread data may have been freed at this point, but it doesn't
        // matter since the syscall will just return EFAULT in that case.
        let r = libc::syscall(SYS_FUTEX, self.futex, FUTEX_WAKE | FUTEX_PRIVATE, 1);
        debug_assert!(r == 0 || r == 1 || r == -1);
        if r == -1 {
            debug_assert_eq!(*libc::__errno_location(), libc::EFAULT);
        }
    }
}
<commit_msg>Use libc::SYS_futex instead of our own definition<commit_after>// Copyright 2016 Amanieu d'Antras
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use std::sync::atomic::{AtomicI32, Ordering};
use std::time::Instant;
use libc;

const FUTEX_WAIT: i32 = 0;
const FUTEX_WAKE: i32 = 1;
const FUTEX_PRIVATE: i32 = 128;

// Helper type for putting a thread to sleep until some other thread wakes it up
pub struct ThreadParker {
    futex: AtomicI32,
}

impl ThreadParker {
    pub fn new() -> ThreadParker {
        ThreadParker {
            futex: AtomicI32::new(0),
        }
    }

    // Prepares the parker. This should be called before adding it to the queue.
    pub unsafe fn prepare_park(&self) {
        self.futex.store(1, Ordering::Relaxed);
    }

    // Checks if the park timed out. This should be called while holding the
    // queue lock after park_until has returned false.
    pub unsafe fn timed_out(&self) -> bool {
        self.futex.load(Ordering::Relaxed) != 0
    }

    // Parks the thread until it is unparked. This should be called after it has
    // been added to the queue, after unlocking the queue.
    pub unsafe fn park(&self) {
        while self.futex.load(Ordering::Acquire) != 0 {
            let r = libc::syscall(libc::SYS_futex, &self.futex, FUTEX_WAIT | FUTEX_PRIVATE, 1, 0);
            debug_assert!(r == 0 || r == -1);
            if r == -1 {
                debug_assert!(
                    *libc::__errno_location() == libc::EINTR
                        || *libc::__errno_location() == libc::EAGAIN
                );
            }
        }
    }

    // Parks the thread until it is unparked or the timeout is reached. This
    // should be called after it has been added to the queue, after unlocking
    // the queue. Returns true if we were unparked and false if we timed out.
    pub unsafe fn park_until(&self, timeout: Instant) -> bool {
        while self.futex.load(Ordering::Acquire) != 0 {
            let now = Instant::now();
            if timeout <= now {
                return false;
            }
            let diff = timeout - now;
            if diff.as_secs() as libc::time_t as u64 != diff.as_secs() {
                // Timeout overflowed, just sleep indefinitely
                self.park();
                return true;
            }
            let ts = libc::timespec {
                tv_sec: diff.as_secs() as libc::time_t,
                tv_nsec: diff.subsec_nanos() as libc::c_long,
            };
            let r = libc::syscall(libc::SYS_futex, &self.futex, FUTEX_WAIT | FUTEX_PRIVATE, 1, &ts);
            debug_assert!(r == 0 || r == -1);
            if r == -1 {
                debug_assert!(
                    *libc::__errno_location() == libc::EINTR
                        || *libc::__errno_location() == libc::EAGAIN
                        || *libc::__errno_location() == libc::ETIMEDOUT
                );
            }
        }
        true
    }

    // Locks the parker to prevent the target thread from exiting. This is
    // necessary to ensure that thread-local ThreadData objects remain valid.
    // This should be called while holding the queue lock.
    pub unsafe fn unpark_lock(&self) -> UnparkHandle {
        // We don't need to lock anything, just clear the state
        self.futex.store(0, Ordering::Release);

        UnparkHandle { futex: &self.futex }
    }
}

// Handle for a thread that is about to be unparked. We need to mark the thread
// as unparked while holding the queue lock, but we delay the actual unparking
// until after the queue lock is released.
pub struct UnparkHandle {
    futex: *const AtomicI32,
}

impl UnparkHandle {
    // Wakes up the parked thread. This should be called after the queue lock is
    // released to avoid blocking the queue for too long.
    pub unsafe fn unpark(self) {
        // The thread data may have been freed at this point, but it doesn't
        // matter since the syscall will just return EFAULT in that case.
        let r = libc::syscall(libc::SYS_futex, self.futex, FUTEX_WAKE | FUTEX_PRIVATE, 1);
        debug_assert!(r == 0 || r == 1 || r == -1);
        if r == -1 {
            debug_assert_eq!(*libc::__errno_location(), libc::EFAULT);
        }
    }
}
<|endoftext|>


<commit_before>// Hound -- A wav encoding and decoding library in Rust
// Copyright 2018 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

#![no_main]

extern crate libfuzzer_sys;
extern crate hound;

use std::io;
use std::fmt::Debug;

fn try_append<S, T>(mut buffer: Vec<u8>, sample_narrow: S, sample_wide: T)
where S: hound::Sample + Copy + Debug + PartialEq,
      T: hound::Sample + Copy + Debug + PartialEq {
    let mut samples_orig: Vec<T> = Vec::new();
    let samples_after: Vec<T>;

    // Read samples first.
    {
        let cursor = io::Cursor::new(&mut buffer);
        let mut reader = hound::WavReader::new(cursor).unwrap();
        for r in reader.samples() {
            match r {
                Ok(x) => samples_orig.push(x),
                // If reading fails, then don't attempt to append. We are only
                // concerned with appending to valid files.
                Err(..) => return,
            }
        }
    }

    // Open in append mode and append one sample for each channel.
    {
        let cursor = io::Cursor::new(&mut buffer);
        let mut writer = hound::WavWriter::append(cursor).unwrap();
        for _ in 0..writer.spec().channels {
            writer.write_sample(sample_narrow).unwrap();
        }
    }

    // Read once more.
    {
        let cursor = io::Cursor::new(buffer);
        let mut reader = hound::WavReader::new(cursor)
            .expect("Reading wav failed after append.");
        samples_after = reader.samples().map(|r| r.unwrap()).collect();
    }

    assert_eq!(&samples_orig[..], &samples_after[..samples_orig.len()]);
    assert_eq!(samples_after[samples_after.len() - 1], sample_wide);
}

#[export_name="rust_fuzzer_test_input"]
pub extern fn go(data: &[u8]) {
    let mut buffer = data.to_vec();
    let spec;
    {
        let cursor = io::Cursor::new(&mut buffer);
        match hound::WavReader::new(cursor) {
            Err(..) => return,
            Ok(reader) => spec = reader.spec(),
        };
    }

    match spec.sample_format {
        hound::SampleFormat::Int => try_append::<i8, i32>(buffer, 41_i8, 41_i32),
        hound::SampleFormat::Float => try_append::<f32, f32>(buffer, 0.41, 0.41),
    }
}
<commit_msg>Fix append fuzzer<commit_after>// Hound -- A wav encoding and decoding library in Rust
// Copyright 2018 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

#![no_main]

extern crate libfuzzer_sys;
extern crate hound;

use std::io;
use std::fmt::Debug;

fn try_append<S, T>(mut buffer: Vec<u8>, sample_narrow: S, sample_wide: T)
where S: hound::Sample + Copy + Debug + PartialEq,
      T: hound::Sample + Copy + Debug + PartialEq {
    let mut samples_orig: Vec<T> = Vec::new();
    let mut samples_after: Vec<T>;

    // Read samples first.
    {
        let cursor = io::Cursor::new(&mut buffer);
        let mut reader = hound::WavReader::new(cursor).unwrap();
        for r in reader.samples() {
            match r {
                Ok(x) => samples_orig.push(x),
                // If reading fails, then don't attempt to append. We are only
                // concerned with appending to valid files.
                Err(..) => return,
            }
        }
    }

    // Open in append mode and append one sample for each channel.
    {
        let cursor = io::Cursor::new(&mut buffer);
        let mut writer = match hound::WavWriter::append(cursor) {
            Ok(w) => w,
            Err(hound::Error::Unsupported) => return,
            Err(err) => panic!("{:?}", err),
        };
        for _ in 0..writer.spec().channels {
            writer.write_sample(sample_narrow).unwrap();
        }
    }

    // Read once more.
    {
        let cursor = io::Cursor::new(buffer);
        let mut reader = hound::WavReader::new(cursor)
            .expect("Reading wav failed after append.");
        samples_after = reader.samples().map(|r| r.unwrap()).collect();
    }

    // Replace NaNs with the given sample.
    for x in &mut samples_orig[..] {
        if *x != *x { *x = sample_wide; }
    }
    for x in &mut samples_after[..] {
        if *x != *x { *x = sample_wide; }
    }

    assert_eq!(&samples_orig[..], &samples_after[..samples_orig.len()]);
    assert_eq!(samples_after[samples_after.len() - 1], sample_wide);
}

#[export_name="rust_fuzzer_test_input"]
pub extern fn go(data: &[u8]) {
    let mut buffer = data.to_vec();
    let spec;
    {
        let cursor = io::Cursor::new(&mut buffer);
        match hound::WavReader::new(cursor) {
            Err(..) => return,
            Ok(reader) => spec = reader.spec(),
        };
    }

    match spec.sample_format {
        hound::SampleFormat::Int => try_append::<i8, i32>(buffer, 41_i8, 41_i32),
        hound::SampleFormat::Float => try_append::<f32, f32>(buffer, 0.41, 0.41),
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use structopt::StructOpt;

use anyhow::Result;

pub mod genes;
pub mod search_xml;
pub mod sequences;
pub mod utils;

use crate::sequences::file_joiner::FileTypes;

#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
enum GenesCommand {
    /// This command does a join between the sequence information, locus information and
    /// gene information. Any sequence not part of a gene is ignored. It then splits
    /// the resulting merged entries by assembly so it produces a directory of files,
    /// one per assmebly. These can then be merge together to produce complete gene
    /// entries. This assumes the locus and sequence information is sorted by a common
    /// id.
    SelectAndSplit {
        /// Filename to read the locus level information from
        #[structopt(parse(from_os_str))]
        locus: PathBuf,

        /// Filename to read the selected members from
        #[structopt(parse(from_os_str))]
        sequences: PathBuf,

        /// Output directory to write to, does not need to exist
        #[structopt(parse(from_os_str))]
        output: PathBuf,
    },

    /// This will take all gene member information and merge them into genes. This needs
    /// enough memory to fit information on all members from an assembly into memory
    /// at once.
    MergeAssembly {
        /// A file of all gene members for a given assembly. The file does not need to be
        /// sorted.
        #[structopt(parse(from_os_str))]
        members: PathBuf,

        /// Filename to write complete gene to
        #[structopt(parse(from_os_str))]
        output: PathBuf,
    },

    AsXml {
        /// File of the complete genes to read
        #[structopt(parse(from_os_str))]
        genes: PathBuf,

        /// Filename to write the xml data to
        #[structopt(parse(from_os_str))]
        xml_output: PathBuf,

        /// Filename to write the counts to
        #[structopt(parse(from_os_str))]
        count_output: PathBuf,
    },
}

#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
enum SequenceCommand {
    Merge {
        #[structopt(parse(from_os_str))]
        base: PathBuf,

        #[structopt(parse(from_os_str))]
        crs: PathBuf,

        #[structopt(parse(from_os_str))]
        feedback: PathBuf,

        #[structopt(parse(from_os_str))]
        go_annotations: PathBuf,

        #[structopt(parse(from_os_str))]
        interacting_proteins: PathBuf,

        #[structopt(parse(from_os_str))]
        interacting_rnas: PathBuf,

        #[structopt(parse(from_os_str))]
        precompute: PathBuf,

        #[structopt(parse(from_os_str))]
        qa_status: PathBuf,

        #[structopt(parse(from_os_str))]
        r2dt_hits: PathBuf,

        #[structopt(parse(from_os_str))]
        rfam_hits: PathBuf,

        #[structopt(parse(from_os_str))]
        orfs: PathBuf,

        #[structopt(parse(from_os_str))]
        /// Filename of the SO term tree metadata.
        so_term_tree: PathBuf,

        #[structopt(parse(from_os_str))]
        /// Filename to write the results to, '-' means stdout
        output: PathBuf,
    },

    Normalize {
        #[structopt(parse(from_os_str))]
        /// Filename of the accessions
        accessions: PathBuf,

        #[structopt(parse(from_os_str))]
        /// Filename for the merged metadata
        metadata: PathBuf,

        #[structopt(parse(from_os_str))]
        /// Filename to write the results to, '-' means stdout
        output: PathBuf,
    },
}

#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
enum Subcommand {
    /// Merge each distinct type of metadata into single merged entries. This assumes that
    /// all files are sorted in the same way. Additionally, the xref file must have at
    /// least one entry for all possible urs_taxids.
    Group {
        /// Type of data to group
        #[structopt(case_insensitive = true)]
        data_type: FileTypes,

        /// Filename to read the results from, '-' means stdin
        #[structopt(parse(from_os_str))]
        path: PathBuf,

        /// The maximum count of the entries.
        max_count: usize,

        /// Filename to write the results to, '-' means stdout
        #[structopt(parse(from_os_str))]
        output: PathBuf,
    },

    /// Set of commands dealing with building data for sequence data export
    Sequences {
        #[structopt(subcommand)]
        command: SequenceCommand,
    },

    /// Commands dealing with building data for gene export
    Genes {
        #[structopt(subcommand)]
        command: GenesCommand,
    },
}

#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
struct Opt {
    /// Set the logging option, more is more verbose.
    #[structopt(short = "v", long = "verbose", parse(from_occurrences))]
    verbose: u32,

    #[structopt(subcommand)]
    command: Subcommand,
}

fn main() -> Result<()> {
    let opt = Opt::from_args();

    let level = match opt.verbose {
        0 => simplelog::LevelFilter::Warn,
        1 => simplelog::LevelFilter::Info,
        2 => simplelog::LevelFilter::Debug,
        _ => simplelog::LevelFilter::Trace,
    };
    simplelog::TermLogger::init(
        level,
        simplelog::Config::default(),
        simplelog::TerminalMode::Stderr,
    )
    .unwrap_or_else(|_| eprintln!("Failed to create logger, ignore"));

    match opt.command {
        Subcommand::Group {
            data_type,
            path,
            max_count,
            output,
        } => match data_type {
            FileTypes::Base => sequences::basic::group(&path, max_count, &output)?,
            FileTypes::Crs => sequences::crs::group(&path, max_count, &output)?,
            FileTypes::Feedback => sequences::feedback::group(&path, max_count, &output)?,
            FileTypes::GoAnnotations => sequences::go_annotation::group(&path, max_count, &output)?,
            FileTypes::InteractingProteins => {
                sequences::interacting_protein::group(&path, max_count, &output)?
            },
            FileTypes::InteractingRnas => {
                sequences::interacting_rna::group(&path, max_count, &output)?
            },
            FileTypes::LocusInfo => genes::region::group(&path, max_count, &output)?,
            FileTypes::Precompute => sequences::precompute::group(&path, max_count, &output)?,
            FileTypes::QaStatus => sequences::qa_status::group(&path, max_count, &output)?,
            FileTypes::R2dtHits => sequences::r2dt::group(&path, max_count, &output)?,
            FileTypes::RfamHits => sequences::rfam_hit::group(&path, max_count, &output)?,
            FileTypes::Orfs => sequences::orf::group(&path, max_count, &output)?,
            FileTypes::SoInfo => Err(anyhow::anyhow!("May not group so info"))?,
        },
        Subcommand::Sequences {
            command,
        } => match command {
            SequenceCommand::Merge {
                base,
                crs,
                feedback,
                go_annotations,
                interacting_proteins,
                interacting_rnas,
                precompute,
                qa_status,
                r2dt_hits,
                rfam_hits,
                orfs,
                so_term_tree,
                output,
            } => sequences::writers::write_merge(
                vec![
                    base,
                    crs,
                    feedback,
                    go_annotations,
                    interacting_proteins,
                    interacting_rnas,
                    precompute,
                    qa_status,
                    r2dt_hits,
                    rfam_hits,
                    orfs,
                    so_term_tree,
                ],
                &output,
            )?,
            SequenceCommand::Normalize {
                accessions,
                metadata,
                output,
            } => sequences::writers::write(&accessions, &metadata, &output)?,
        },
        Subcommand::Genes {
            command,
        } => match command {
            GenesCommand::SelectAndSplit {
                locus,
                sequences,
                output,
            } => genes::writers::write_selected_members(&locus, &sequences, &output)?,
            GenesCommand::MergeAssembly {
                members,
                output,
            } => genes::writers::write_merged_members(&members, &output)?,
            GenesCommand::AsXml {
                genes,
                xml_output,
                count_output,
            } => genes::writers::write_search_files(&genes, &xml_output, &count_output)?,
        },
    }

    Ok(())
}
<commit_msg>Use a enum specific to group<commit_after>use std::path::PathBuf;
use structopt::StructOpt;

use anyhow::Result;

use strum_macros::{
    Display,
    EnumIter,
    EnumString,
};

pub mod genes;
pub mod search_xml;
pub mod sequences;
pub mod utils;

#[derive(Debug, Display, PartialEq, Eq, Hash, EnumString, EnumIter)]
#[strum(serialize_all = "kebab-case")]
pub enum Groupable {
    #[strum(ascii_case_insensitive)]
    Base,

    #[strum(ascii_case_insensitive)]
    Crs,

    #[strum(ascii_case_insensitive)]
    Feedback,

    #[strum(ascii_case_insensitive)]
    GoAnnotations,

    #[strum(ascii_case_insensitive)]
    InteractingProteins,

    #[strum(ascii_case_insensitive)]
    InteractingRnas,

    #[strum(ascii_case_insensitive)]
    RegionInfo,

    #[strum(ascii_case_insensitive)]
    Orfs,

    #[strum(ascii_case_insensitive)]
    Precompute,

    #[strum(ascii_case_insensitive)]
    QaStatus,

    #[strum(ascii_case_insensitive)]
    R2dtHits,

    #[strum(ascii_case_insensitive)]
    RfamHits,

    #[strum(ascii_case_insensitive)]
    SoInfo,
}

#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
enum GenesCommand {
    /// This command does a join between the sequence information, locus information and
    /// gene information. Any sequence not part of a gene is ignored. It then splits
    /// the resulting merged entries by assembly so it produces a directory of files,
    /// one per assmebly. These can then be merge together to produce complete gene
    /// entries. This assumes the locus and sequence information is sorted by a common
    /// id.
    SelectAndSplit {
        /// Filename to read the locus level information from
        #[structopt(parse(from_os_str))]
        locus: PathBuf,

        /// Filename to read the selected members from
        #[structopt(parse(from_os_str))]
        sequences: PathBuf,

        /// Output directory to write to, does not need to exist
        #[structopt(parse(from_os_str))]
        output: PathBuf,
    },

    /// This will take all gene member information and merge them into genes. This needs
    /// enough memory to fit information on all members from an assembly into memory
    /// at once.
    MergeAssembly {
        /// A file of all gene members for a given assembly. The file does not need to be
        /// sorted.
        #[structopt(parse(from_os_str))]
        members: PathBuf,

        /// Filename to write complete gene to
        #[structopt(parse(from_os_str))]
        output: PathBuf,
    },

    AsXml {
        /// File of the complete genes to read
        #[structopt(parse(from_os_str))]
        genes: PathBuf,

        /// Filename to write the xml data to
        #[structopt(parse(from_os_str))]
        xml_output: PathBuf,

        /// Filename to write the counts to
        #[structopt(parse(from_os_str))]
        count_output: PathBuf,
    },
}

#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
enum SequenceCommand {
    Merge {
        #[structopt(parse(from_os_str))]
        base: PathBuf,

        #[structopt(parse(from_os_str))]
        crs: PathBuf,

        #[structopt(parse(from_os_str))]
        feedback: PathBuf,

        #[structopt(parse(from_os_str))]
        go_annotations: PathBuf,

        #[structopt(parse(from_os_str))]
        interacting_proteins: PathBuf,

        #[structopt(parse(from_os_str))]
        interacting_rnas: PathBuf,

        #[structopt(parse(from_os_str))]
        precompute: PathBuf,

        #[structopt(parse(from_os_str))]
        qa_status: PathBuf,

        #[structopt(parse(from_os_str))]
        r2dt_hits: PathBuf,

        #[structopt(parse(from_os_str))]
        rfam_hits: PathBuf,

        #[structopt(parse(from_os_str))]
        orfs: PathBuf,

        #[structopt(parse(from_os_str))]
        /// Filename of the SO term tree metadata.
        so_term_tree: PathBuf,

        #[structopt(parse(from_os_str))]
        /// Filename to write the results to, '-' means stdout
        output: PathBuf,
    },

    Normalize {
        #[structopt(parse(from_os_str))]
        /// Filename of the accessions
        accessions: PathBuf,

        #[structopt(parse(from_os_str))]
        /// Filename for the merged metadata
        metadata: PathBuf,

        #[structopt(parse(from_os_str))]
        /// Filename to write the results to, '-' means stdout
        output: PathBuf,
    },
}

#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
enum Subcommand {
    /// Merge each distinct type of metadata into single merged entries. This assumes that
    /// all files are sorted in the same way. Additionally, the xref file must have at
    /// least one entry for all possible urs_taxids.
    Group {
        /// Type of data to group
        #[structopt(case_insensitive = true)]
        data_type: Groupable,

        /// Filename to read the results from, '-' means stdin
        #[structopt(parse(from_os_str))]
        path: PathBuf,

        /// The maximum count of the entries.
        max_count: usize,

        /// Filename to write the results to, '-' means stdout
        #[structopt(parse(from_os_str))]
        output: PathBuf,
    },

    /// Set of commands dealing with building data for sequence data export
    Sequences {
        #[structopt(subcommand)]
        command: SequenceCommand,
    },

    /// Commands dealing with building data for gene export
    Genes {
        #[structopt(subcommand)]
        command: GenesCommand,
    },
}

#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
struct Opt {
    /// Set the logging option, more is more verbose.
    #[structopt(short = "v", long = "verbose", parse(from_occurrences))]
    verbose: u32,

    #[structopt(subcommand)]
    command: Subcommand,
}

fn main() -> Result<()> {
    let opt = Opt::from_args();

    let level = match opt.verbose {
        0 => simplelog::LevelFilter::Warn,
        1 => simplelog::LevelFilter::Info,
        2 => simplelog::LevelFilter::Debug,
        _ => simplelog::LevelFilter::Trace,
    };
    simplelog::TermLogger::init(
        level,
        simplelog::Config::default(),
        simplelog::TerminalMode::Stderr,
    )
    .unwrap_or_else(|_| eprintln!("Failed to create logger, ignore"));

    match opt.command {
        Subcommand::Group {
            data_type,
            path,
            max_count,
            output,
        } => match data_type {
            Groupable::Base => sequences::basic::group(&path, max_count, &output)?,
            Groupable::Crs => sequences::crs::group(&path, max_count, &output)?,
            Groupable::Feedback => sequences::feedback::group(&path, max_count, &output)?,
            Groupable::GoAnnotations => sequences::go_annotation::group(&path, max_count, &output)?,
            Groupable::InteractingProteins => {
                sequences::interacting_protein::group(&path, max_count, &output)?
            },
            Groupable::InteractingRnas => {
                sequences::interacting_rna::group(&path, max_count, &output)?
            },
            Groupable::RegionInfo => genes::region::group(&path, max_count, &output)?,
            Groupable::Precompute => sequences::precompute::group(&path, max_count, &output)?,
            Groupable::QaStatus => sequences::qa_status::group(&path, max_count, &output)?,
            Groupable::R2dtHits => sequences::r2dt::group(&path, max_count, &output)?,
            Groupable::RfamHits => sequences::rfam_hit::group(&path, max_count, &output)?,
            Groupable::Orfs => sequences::orf::group(&path, max_count, &output)?,
            Groupable::SoInfo => Err(anyhow::anyhow!("May not group so info"))?,
        },
        Subcommand::Sequences {
            command,
        } => match command {
            SequenceCommand::Merge {
                base,
                crs,
                feedback,
                go_annotations,
                interacting_proteins,
                interacting_rnas,
                precompute,
                qa_status,
                r2dt_hits,
                rfam_hits,
                orfs,
                so_term_tree,
                output,
            } => sequences::writers::write_merge(
                vec![
                    base,
                    crs,
                    feedback,
                    go_annotations,
                    interacting_proteins,
                    interacting_rnas,
                    precompute,
                    qa_status,
                    r2dt_hits,
                    rfam_hits,
                    orfs,
                    so_term_tree,
                ],
                &output,
            )?,
            SequenceCommand::Normalize {
                accessions,
                metadata,
                output,
            } => sequences::writers::write(&accessions, &metadata, &output)?,
        },
        Subcommand::Genes {
            command,
        } => match command {
            GenesCommand::SelectAndSplit {
                locus,
                sequences,
                output,
            } => genes::writers::write_selected_members(&locus, &sequences, &output)?,
            GenesCommand::MergeAssembly {
                members,
                output,
            } => genes::writers::write_merged_members(&members, &output)?,
            GenesCommand::AsXml {
                genes,
                xml_output,
                count_output,
            } => genes::writers::write_search_files(&genes, &xml_output, &count_output)?,
        },
    }

    Ok(())
}
<|endoftext|>


<commit_before>#![feature(phase)]
#![crate_name = "triangle"]

#[phase(plugin)]
extern crate gfx_macros;
extern crate getopts;
extern crate gfx;
extern crate glfw;
extern crate glfw_platform;
extern crate gl_init;
extern crate gl_init_platform;
extern crate native;

use glfw_platform::BuilderExtension;

#[vertex_format]
struct Vertex {
    pos: [f32, ..2],
    color: [f32, ..3],
}

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120
    attribute vec2 pos;
    attribute vec3 color;
    varying vec4 v_Color;
    void main() {
        v_Color = vec4(color, 1.0);
        gl_Position = vec4(pos, 0.0, 1.0);
    }
"
GLSL_150: b"
    #version 150 core
    in vec2 pos;
    in vec3 color;
    out vec4 v_Color;
    void main() {
        v_Color = vec4(color, 1.0);
        gl_Position = vec4(pos, 0.0, 1.0);
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120
    varying vec4 v_Color;
    void main() {
        gl_FragColor = v_Color;
    }
"
GLSL_150: b"
    #version 150 core
    in vec4 v_Color;
    out vec4 o_Color;
    void main() {
        o_Color = v_Color;
    }
"
};

// We need to run on the main thread for GLFW, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn main() {
    // checking for the --gl-init flag
    let use_gl_init = {
        use std::os;
        use getopts::{optflag, getopts};

        let args: Vec<String> = os::args();

        let options = [
            optflag("i", "gl-init", "use gl-init instead of glfw")
        ];

        let matches = match getopts(args.tail(), options) {
            Ok(m) => { m }
            Err(f) => {
                println!("{}", f.to_string());
                println!("Usage: {} [options]", args[0]);
                println!("--gl-init\t\tUse gl-init instead of glfw");
                return
            }
        };

        matches.opt_present("i")
    };

    if use_gl_init {
        let window = gl_init_platform::Window::new().unwrap();
        window.set_title("[gl-init] Triangle example #gfx-rs!");
        unsafe { window.make_current() };

        let (w, h) = window.get_inner_size().unwrap();

        let mut device = gfx::build()
            .with_context(&window)
            .with_provider(&window)
            .with_queue_size(1)
            .spawn(proc(r) render(r, w as u16, h as u16))
            .unwrap();

        'main: loop {
            // quit when Esc is pressed.
            for event in window.poll_events() {
                match event {
                    gl_init::Pressed(gl_init::Escape) => break 'main,
                    gl_init::Closed => break 'main,
                    _ => {},
                }
            }
            device.update();
        }
    } else {
        let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

        let (mut window, events) = glfw_platform::WindowBuilder::new(&glfw)
            .title("[GLFW] Triangle example #gfx-rs!")
            .try_modern_context_hints()
            .create()
            .expect("Failed to create GLFW window.");

        glfw.set_error_callback(glfw::FAIL_ON_ERRORS);
        window.set_key_polling(true); // so we can quit when Esc is pressed
        let (w, h) = window.get_framebuffer_size();

        let mut device = gfx::build()
            .with_glfw_window(&mut window)
            .with_queue_size(1)
            .spawn(proc(r) render(r, w as u16, h as u16))
            .unwrap();

        'main: loop {
            glfw.poll_events();
            if window.should_close() {
                break 'main;
            }
            // quit when Esc is pressed.
            for (_, event) in glfw::flush_messages(&events) {
                match event {
                    glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _) => break 'main,
                    _ => {},
                }
            }
            device.update();
        }
    }
}

fn render(mut renderer: gfx::Renderer, width: u16, height: u16) {
    let frame = gfx::Frame::new(width as u16, height as u16);
    let state = gfx::DrawState::new();

    let vertex_data = vec![
        Vertex { pos: [ -0.5, -0.5 ], color: [1.0, 0.0, 0.0] },
        Vertex { pos: [ 0.5, -0.5 ], color: [0.0, 1.0, 0.0]  },
        Vertex { pos: [ 0.0, 0.5 ], color: [0.0, 0.0, 1.0]  }
    ];

    let mesh = renderer.create_mesh(vertex_data);
    let program = renderer.create_program(VERTEX_SRC.clone(), FRAGMENT_SRC.clone());

    let clear = gfx::ClearData {
        color: Some(gfx::Color([0.3, 0.3, 0.3, 1.0])),
        depth: None,
        stencil: None,
    };

    while !renderer.should_finish() {
        renderer.clear(clear, frame);
        renderer.draw(&mesh, mesh.get_slice(), &frame, &program, &state)
            .unwrap();
        renderer.end_frame();
        for err in renderer.errors() {
            println!("Renderer error: {}", err);
        }
    }
}
<commit_msg>Fix gl_init events<commit_after>#![feature(phase)]
#![crate_name = "triangle"]

#[phase(plugin)]
extern crate gfx_macros;
extern crate getopts;
extern crate gfx;
extern crate glfw;
extern crate glfw_platform;
extern crate gl_init;
extern crate gl_init_platform;
extern crate native;

use glfw_platform::BuilderExtension;

#[vertex_format]
struct Vertex {
    pos: [f32, ..2],
    color: [f32, ..3],
}

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120
    attribute vec2 pos;
    attribute vec3 color;
    varying vec4 v_Color;
    void main() {
        v_Color = vec4(color, 1.0);
        gl_Position = vec4(pos, 0.0, 1.0);
    }
"
GLSL_150: b"
    #version 150 core
    in vec2 pos;
    in vec3 color;
    out vec4 v_Color;
    void main() {
        v_Color = vec4(color, 1.0);
        gl_Position = vec4(pos, 0.0, 1.0);
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_120: b"
    #version 120
    varying vec4 v_Color;
    void main() {
        gl_FragColor = v_Color;
    }
"
GLSL_150: b"
    #version 150 core
    in vec4 v_Color;
    out vec4 o_Color;
    void main() {
        o_Color = v_Color;
    }
"
};

// We need to run on the main thread for GLFW, so ensure we are using the `native` runtime. This is
// technically not needed, since this is the default, but it's not guaranteed.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
     native::start(argc, argv, main)
}

fn main() {
    // checking for the --gl-init flag
    let use_gl_init = {
        use std::os;
        use getopts::{optflag, getopts};

        let args: Vec<String> = os::args();

        let options = [
            optflag("i", "gl-init", "use gl-init instead of glfw")
        ];

        let matches = match getopts(args.tail(), options) {
            Ok(m) => { m }
            Err(f) => {
                println!("{}", f.to_string());
                println!("Usage: {} [options]", args[0]);
                println!("--gl-init\t\tUse gl-init instead of glfw");
                return
            }
        };

        matches.opt_present("i")
    };

    if use_gl_init {
        let window = gl_init_platform::Window::new().unwrap();
        window.set_title("[gl-init] Triangle example #gfx-rs!");
        unsafe { window.make_current() };

        let (w, h) = window.get_inner_size().unwrap();

        let mut device = gfx::build()
            .with_context(&window)
            .with_provider(&window)
            .with_queue_size(1)
            .spawn(proc(r) render(r, w as u16, h as u16))
            .unwrap();

        'main: loop {
            // quit when Esc is pressed.
            for event in window.poll_events() {
                match event {
                    gl_init::KeyboardInput(_, _, Some(gl_init::Escape), _) => break 'main,
                    gl_init::Closed => break 'main,
                    _ => {},
                }
            }
            device.update();
        }
    } else {
        let glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

        let (mut window, events) = glfw_platform::WindowBuilder::new(&glfw)
            .title("[GLFW] Triangle example #gfx-rs!")
            .try_modern_context_hints()
            .create()
            .expect("Failed to create GLFW window.");

        glfw.set_error_callback(glfw::FAIL_ON_ERRORS);
        window.set_key_polling(true); // so we can quit when Esc is pressed
        let (w, h) = window.get_framebuffer_size();

        let mut device = gfx::build()
            .with_glfw_window(&mut window)
            .with_queue_size(1)
            .spawn(proc(r) render(r, w as u16, h as u16))
            .unwrap();

        'main: loop {
            glfw.poll_events();
            if window.should_close() {
                break 'main;
            }
            // quit when Esc is pressed.
            for (_, event) in glfw::flush_messages(&events) {
                match event {
                    glfw::KeyEvent(glfw::KeyEscape, _, glfw::Press, _) => break 'main,
                    _ => {},
                }
            }
            device.update();
        }
    }
}

fn render(mut renderer: gfx::Renderer, width: u16, height: u16) {
    let frame = gfx::Frame::new(width as u16, height as u16);
    let state = gfx::DrawState::new();

    let vertex_data = vec![
        Vertex { pos: [ -0.5, -0.5 ], color: [1.0, 0.0, 0.0] },
        Vertex { pos: [ 0.5, -0.5 ], color: [0.0, 1.0, 0.0]  },
        Vertex { pos: [ 0.0, 0.5 ], color: [0.0, 0.0, 1.0]  }
    ];

    let mesh = renderer.create_mesh(vertex_data);
    let program = renderer.create_program(VERTEX_SRC.clone(), FRAGMENT_SRC.clone());

    let clear = gfx::ClearData {
        color: Some(gfx::Color([0.3, 0.3, 0.3, 1.0])),
        depth: None,
        stencil: None,
    };

    while !renderer.should_finish() {
        renderer.clear(clear, frame);
        renderer.draw(&mesh, mesh.get_slice(), &frame, &program, &state)
            .unwrap();
        renderer.end_frame();
        for err in renderer.errors() {
            println!("Renderer error: {}", err);
        }
    }
}
<|endoftext|>


<commit_before>extern crate shootr;

extern crate specs;
extern crate chrono;

use self::specs::{DispatcherBuilder, World};
use self::chrono::prelude::*;

use shootr::engine::{Msg, Engine, EventHandler, Id};
use shootr::ecs::{comp, sys, res};
use shootr::util::read_env_var;
use res::Ids;
use std::sync::{Arc, RwLock};

fn main() {
    shootr::engine::execute::<Handler>();
}
struct Handler {
    engine: Engine,
    ids: Ids,
}
impl EventHandler for Handler {
    fn new(engine: Engine) -> Self {
        Handler {
            engine,
            ids: Ids(Arc::new(RwLock::new(Vec::new()))),
        }
    }
    fn main_loop(&self) {
        let mut world = World::new();
        world.register::<comp::Pos>();
        world.register::<comp::Vel>();
        world.add_resource(self.engine.clone());
        world.add_resource(self.ids.clone());
        for _ in 0..1 {
            world
                .create_entity()
                .with(comp::Vel { x: 3, y: 2 })
                .with(comp::Pos { x: 500, y: 500 })
                .build();
        }

        let mut physics = DispatcherBuilder::new()
            .add(sys::Physics, "physics", &[])
            .build();
        let mut renderer = DispatcherBuilder::new().add(sys::Send, "send", &[]).build();
        physics.dispatch(&mut world.res);

        let mut lag: i64 = 0;
        let mut previous = Utc::now();
        let ms_per_update = read_env_var("CORE_MS_PER_UPDATE").parse::<i64>().expect(
            "Failed to parse environmental variable as integer",
        );

        loop {
            let current = Utc::now();
            let elapsed = elapsed_time(previous, current);
            previous = current;
            lag += elapsed;
            while lag >= ms_per_update {
                physics.dispatch(&mut world.res);
                lag -= ms_per_update;
            }
            let progress = lag as f64 / ms_per_update as f64;
            world.add_resource(res::TimeProgress(progress));
            renderer.dispatch(&mut world.res);
        }
    }
    fn message(&self, msg: &Msg) {
        println!("Received message: {}", msg.content);
    }
    fn connect(&self, id: Id) -> bool {
        self.ids.write().unwrap().push(id);
        true
    }
    fn disconnect(&self, id: Id) {
        let mut ids = self.ids.write().unwrap();
        let pos = ids.iter().position(|&x| x == id).expect(
            "Tried to remove id that was not added in the first place",
        );
        ids.remove(pos);
    }
}

fn elapsed_time(from: chrono::DateTime<Utc>, to: chrono::DateTime<Utc>) -> i64 {
    to.signed_duration_since(from).num_microseconds().expect(
        "Too much time passed between DateTimes",
    )
}
<commit_msg>Core: Resolve #2<commit_after>extern crate shootr;

extern crate specs;
extern crate chrono;

use self::specs::{DispatcherBuilder, World};
use self::chrono::prelude::*;

use shootr::engine::{Msg, Engine, EventHandler, Id};
use shootr::ecs::{comp, sys, res};
use shootr::util::read_env_var;
use res::Ids;

use std::sync::{Arc, RwLock};
use std::thread::sleep;
use std::time::Duration;

fn main() {
    shootr::engine::execute::<Handler>();
}
struct Handler {
    engine: Engine,
    ids: Ids,
}
impl EventHandler for Handler {
    fn new(engine: Engine) -> Self {
        Handler {
            engine,
            ids: Ids(Arc::new(RwLock::new(Vec::new()))),
        }
    }
    fn main_loop(&self) {
        let mut world = World::new();
        world.register::<comp::Pos>();
        world.register::<comp::Vel>();
        world.add_resource(self.engine.clone());
        world.add_resource(self.ids.clone());
        for _ in 0..1 {
            world
                .create_entity()
                .with(comp::Vel { x: 3, y: 2 })
                .with(comp::Pos { x: 500, y: 500 })
                .build();
        }

        let mut physics = DispatcherBuilder::new()
            .add(sys::Physics, "physics", &[])
            .build();
        let mut renderer = DispatcherBuilder::new().add(sys::Send, "send", &[]).build();
        physics.dispatch(&mut world.res);

        let mut lag: u64 = 0;
        let mut previous = Utc::now();
        let ms_per_update = read_env_var("CORE_MS_PER_UPDATE").parse::<u64>().expect(
            "Failed to parse environmental variable as integer",
        );

        loop {
            let current = Utc::now();
            let elapsed = elapsed_time(previous, current);
            previous = current;
            lag += elapsed;
            while lag >= ms_per_update {
                physics.dispatch(&mut world.res);
                lag -= ms_per_update;
            }
            let progress = lag as f64 / ms_per_update as f64;
            world.add_resource(res::TimeProgress(progress));
            renderer.dispatch(&mut world.res);
            sleep(Duration::from_millis(ms_per_update - lag));
        }
    }
    fn message(&self, msg: &Msg) {
        println!("Received message: {}", msg.content);
    }
    fn connect(&self, id: Id) -> bool {
        self.ids.write().unwrap().push(id);
        true
    }
    fn disconnect(&self, id: Id) {
        let mut ids = self.ids.write().unwrap();
        let pos = ids.iter().position(|&x| x == id).expect(
            "Tried to remove id that was not added in the first place",
        );

        ids.remove(pos);
    }
}

fn elapsed_time(from: chrono::DateTime<Utc>, to: chrono::DateTime<Utc>) -> u64 {
    to.signed_duration_since(from).num_milliseconds() as u64
}
<|endoftext|>


<commit_before>use std::io::Write;

fn main() {
    let args = std::env::args();
    if args.len() != 2 {
        let _ = writeln!(std::io::stderr(), "Please enter exactly one argument");
        std::process::exit(1);
    }
    if let Some(last_arg) = args.last() {
        let mut word: Vec<_> = last_arg.chars().collect();
        generate_permutations(word.len() - 1, &mut word);
    }
}

fn generate_permutations(n: usize, a: &mut Vec<char>) {
    if n == 0 {
        println!("{}", a.clone().into_iter().collect::<String>());
    } else {
        for i in 0..n+1 {
            generate_permutations(n - 1, a);
            a.swap(if n % 2 == 0 { i } else { 0 }, n);
        }
    }
}
<commit_msg>Add comment<commit_after>use std::io::Write; // Needed for writing to stderr

fn main() {
    let args = std::env::args();
    if args.len() != 2 {
        let _ = writeln!(std::io::stderr(), "Please enter exactly one argument");
        std::process::exit(1);
    }
    if let Some(last_arg) = args.last() {
        let mut word: Vec<_> = last_arg.chars().collect();
        generate_permutations(word.len() - 1, &mut word);
    }
}

fn generate_permutations(n: usize, a: &mut Vec<char>) {
    if n == 0 {
        println!("{}", a.clone().into_iter().collect::<String>());
    } else {
        for i in 0..n+1 {
            generate_permutations(n - 1, a);
            a.swap(if n % 2 == 0 { i } else { 0 }, n);
        }
    }
}
<|endoftext|>


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

// FIXME: this modules relies on strings and AST way too much, and it should be
// rewritten (matklad 2020-05-07)
use std::{
    convert::From,
    fmt::{self, Display},
};

use hir::{Docs, Documentation, HasSource, HirDisplay};
use ra_ide_db::RootDatabase;
use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner};
use stdx::SepBy;

use crate::display::{generic_parameters, where_predicates};

#[derive(Debug)]
pub enum CallableKind {
    Function,
    StructConstructor,
    VariantConstructor,
    Macro,
}

/// Contains information about a function signature
#[derive(Debug)]
pub struct FunctionSignature {
    pub kind: CallableKind,
    /// Optional visibility
    pub visibility: Option<String>,
    /// Qualifiers like `async`, `unsafe`, ...
    pub qualifier: FunctionQualifier,
    /// Name of the function
    pub name: Option<String>,
    /// Documentation for the function
    pub doc: Option<Documentation>,
    /// Generic parameters
    pub generic_parameters: Vec<String>,
    /// Parameters of the function
    pub parameters: Vec<String>,
    /// Parameter names of the function
    pub parameter_names: Vec<String>,
    /// Parameter types of the function
    pub parameter_types: Vec<String>,
    /// Optional return type
    pub ret_type: Option<String>,
    /// Where predicates
    pub where_predicates: Vec<String>,
    /// Self param presence
    pub has_self_param: bool,
}

#[derive(Debug, Default)]
pub struct FunctionQualifier {
    // `async` and `const` are mutually exclusive. Do we need to enforcing it here?
    pub is_async: bool,
    pub is_const: bool,
    pub is_unsafe: bool,
    /// The string `extern ".."`
    pub extern_abi: Option<String>,
}

impl FunctionSignature {
    pub(crate) fn with_doc_opt(mut self, doc: Option<Documentation>) -> Self {
        self.doc = doc;
        self
    }

    pub(crate) fn from_hir(db: &RootDatabase, function: hir::Function) -> Self {
        let doc = function.docs(db);
        let ast_node = function.source(db).value;
        FunctionSignature::from(&ast_node).with_doc_opt(doc)
    }

    pub(crate) fn from_struct(db: &RootDatabase, st: hir::Struct) -> Option<Self> {
        let node: ast::StructDef = st.source(db).value;
        if let ast::StructKind::Record(_) = node.kind() {
            return None;
        };

        let mut params = vec![];
        let mut parameter_types = vec![];
        for field in st.fields(db).into_iter() {
            let ty = field.signature_ty(db);
            let raw_param = format!("{}", ty.display(db));

            if let Some(param_type) = raw_param.split(':').nth(1).and_then(|it| it.get(1..)) {
                parameter_types.push(param_type.to_string());
            } else {
                // useful when you have tuple struct
                parameter_types.push(raw_param.clone());
            }
            params.push(raw_param);
        }

        Some(
            FunctionSignature {
                kind: CallableKind::StructConstructor,
                visibility: node.visibility().map(|n| n.syntax().text().to_string()),
                // Do we need `const`?
                qualifier: Default::default(),
                name: node.name().map(|n| n.text().to_string()),
                ret_type: node.name().map(|n| n.text().to_string()),
                parameters: params,
                parameter_names: vec![],
                parameter_types,
                generic_parameters: generic_parameters(&node),
                where_predicates: where_predicates(&node),
                doc: None,
                has_self_param: false,
            }
            .with_doc_opt(st.docs(db)),
        )
    }

    pub(crate) fn from_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Option<Self> {
        let node: ast::EnumVariant = variant.source(db).value;
        match node.kind() {
            ast::StructKind::Record(_) | ast::StructKind::Unit => return None,
            _ => (),
        };

        let parent_name = variant.parent_enum(db).name(db).to_string();

        let name = format!("{}::{}", parent_name, variant.name(db));

        let mut params = vec![];
        let mut parameter_types = vec![];
        for field in variant.fields(db).into_iter() {
            let ty = field.signature_ty(db);
            let raw_param = format!("{}", ty.display(db));
            if let Some(param_type) = raw_param.split(':').nth(1).and_then(|it| it.get(1..)) {
                parameter_types.push(param_type.to_string());
            } else {
                // The unwrap_or_else is useful when you have tuple
                parameter_types.push(raw_param);
            }
            let name = field.name(db);

            params.push(format!("{}: {}", name, ty.display(db)));
        }

        Some(
            FunctionSignature {
                kind: CallableKind::VariantConstructor,
                visibility: None,
                // Do we need `const`?
                qualifier: Default::default(),
                name: Some(name),
                ret_type: None,
                parameters: params,
                parameter_names: vec![],
                parameter_types,
                generic_parameters: vec![],
                where_predicates: vec![],
                doc: None,
                has_self_param: false,
            }
            .with_doc_opt(variant.docs(db)),
        )
    }

    pub(crate) fn from_macro(db: &RootDatabase, macro_def: hir::MacroDef) -> Option<Self> {
        let node: ast::MacroCall = macro_def.source(db).value;

        let params = vec![];

        Some(
            FunctionSignature {
                kind: CallableKind::Macro,
                visibility: None,
                qualifier: Default::default(),
                name: node.name().map(|n| n.text().to_string()),
                ret_type: None,
                parameters: params,
                parameter_names: vec![],
                parameter_types: vec![],
                generic_parameters: vec![],
                where_predicates: vec![],
                doc: None,
                has_self_param: false,
            }
            .with_doc_opt(macro_def.docs(db)),
        )
    }
}

impl From<&'_ ast::FnDef> for FunctionSignature {
    fn from(node: &ast::FnDef) -> FunctionSignature {
        fn strip_leading_underscore(name: String) -> String {
            if name.starts_with("_") {
                name.get(1..).unwrap_or_default().to_string()
            } else {
                name
            }
        }

        fn param_list(node: &ast::FnDef) -> (bool, Vec<String>, Vec<String>) {
            let mut res = vec![];
            let mut res_types = vec![];
            let mut has_self_param = false;
            if let Some(param_list) = node.param_list() {
                if let Some(self_param) = param_list.self_param() {
                    has_self_param = true;
                    let raw_param = self_param.syntax().text().to_string();

                    res_types.push(
                        raw_param
                            .split(':')
                            .nth(1)
                            .and_then(|it| it.get(1..))
                            .unwrap_or_else(|| "Self")
                            .to_string(),
                    );
                    res.push(raw_param);
                }

                res.extend(param_list.params().map(|param| param.syntax().text().to_string()));
                res_types.extend(param_list.params().map(|param| {
                    let param_text = param.syntax().text().to_string();
                    match param_text.split(':').nth(1).and_then(|it| it.get(1..)) {
                        Some(it) => it.to_string(),
                        None => param_text,
                    }
                }));
            }
            (has_self_param, res, res_types)
        }

        fn param_name_list(node: &ast::FnDef) -> Vec<String> {
            let mut res = vec![];
            if let Some(param_list) = node.param_list() {
                if let Some(self_param) = param_list.self_param() {
                    res.push(self_param.syntax().text().to_string())
                }

                res.extend(
                    param_list
                        .params()
                        .map(|param| {
                            Some(strip_leading_underscore(
                                param
                                    .pat()?
                                    .syntax()
                                    .descendants()
                                    .find_map(ast::Name::cast)?
                                    .text()
                                    .to_string(),
                            ))
                        })
                        .map(|param| param.unwrap_or_default()),
                );
            }
            res
        }

        let (has_self_param, parameters, parameter_types) = param_list(node);

        FunctionSignature {
            kind: CallableKind::Function,
            visibility: node.visibility().map(|n| n.syntax().text().to_string()),
            qualifier: FunctionQualifier {
                is_async: node.async_token().is_some(),
                is_const: node.const_token().is_some(),
                is_unsafe: node.unsafe_token().is_some(),
                extern_abi: node.abi().map(|n| n.to_string()),
            },
            name: node.name().map(|n| n.text().to_string()),
            ret_type: node
                .ret_type()
                .and_then(|r| r.type_ref())
                .map(|n| n.syntax().text().to_string()),
            parameters,
            parameter_names: param_name_list(node),
            parameter_types,
            generic_parameters: generic_parameters(node),
            where_predicates: where_predicates(node),
            // docs are processed separately
            doc: None,
            has_self_param,
        }
    }
}

impl Display for FunctionSignature {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(t) = &self.visibility {
            write!(f, "{} ", t)?;
        }

        if self.qualifier.is_async {
            write!(f, "async ")?;
        }

        if self.qualifier.is_const {
            write!(f, "const ")?;
        }

        if self.qualifier.is_unsafe {
            write!(f, "unsafe ")?;
        }

        if let Some(extern_abi) = &self.qualifier.extern_abi {
            // Keyword `extern` is included in the string.
            write!(f, "{} ", extern_abi)?;
        }

        if let Some(name) = &self.name {
            match self.kind {
                CallableKind::Function => write!(f, "fn {}", name)?,
                CallableKind::StructConstructor => write!(f, "struct {}", name)?,
                CallableKind::VariantConstructor => write!(f, "{}", name)?,
                CallableKind::Macro => write!(f, "{}!", name)?,
            }
        }

        if !self.generic_parameters.is_empty() {
            write!(f, "{}", self.generic_parameters.iter().sep_by(", ").surround_with("<", ">"))?;
        }

        write!(f, "{}", self.parameters.iter().sep_by(", ").surround_with("(", ")"))?;

        if let Some(t) = &self.ret_type {
            write!(f, " -> {}", t)?;
        }

        if !self.where_predicates.is_empty() {
            write!(f, "\nwhere {}", self.where_predicates.iter().sep_by(",\n      "))?;
        }

        Ok(())
    }
}
<commit_msg>Use built-in method<commit_after>//! FIXME: write short doc here

// FIXME: this modules relies on strings and AST way too much, and it should be
// rewritten (matklad 2020-05-07)
use std::{
    convert::From,
    fmt::{self, Display},
};

use hir::{Docs, Documentation, HasSource, HirDisplay};
use ra_ide_db::RootDatabase;
use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner};
use stdx::SepBy;

use crate::display::{generic_parameters, where_predicates};

#[derive(Debug)]
pub enum CallableKind {
    Function,
    StructConstructor,
    VariantConstructor,
    Macro,
}

/// Contains information about a function signature
#[derive(Debug)]
pub struct FunctionSignature {
    pub kind: CallableKind,
    /// Optional visibility
    pub visibility: Option<String>,
    /// Qualifiers like `async`, `unsafe`, ...
    pub qualifier: FunctionQualifier,
    /// Name of the function
    pub name: Option<String>,
    /// Documentation for the function
    pub doc: Option<Documentation>,
    /// Generic parameters
    pub generic_parameters: Vec<String>,
    /// Parameters of the function
    pub parameters: Vec<String>,
    /// Parameter names of the function
    pub parameter_names: Vec<String>,
    /// Parameter types of the function
    pub parameter_types: Vec<String>,
    /// Optional return type
    pub ret_type: Option<String>,
    /// Where predicates
    pub where_predicates: Vec<String>,
    /// Self param presence
    pub has_self_param: bool,
}

#[derive(Debug, Default)]
pub struct FunctionQualifier {
    // `async` and `const` are mutually exclusive. Do we need to enforcing it here?
    pub is_async: bool,
    pub is_const: bool,
    pub is_unsafe: bool,
    /// The string `extern ".."`
    pub extern_abi: Option<String>,
}

impl FunctionSignature {
    pub(crate) fn with_doc_opt(mut self, doc: Option<Documentation>) -> Self {
        self.doc = doc;
        self
    }

    pub(crate) fn from_hir(db: &RootDatabase, function: hir::Function) -> Self {
        let doc = function.docs(db);
        let ast_node = function.source(db).value;
        FunctionSignature::from(&ast_node).with_doc_opt(doc)
    }

    pub(crate) fn from_struct(db: &RootDatabase, st: hir::Struct) -> Option<Self> {
        let node: ast::StructDef = st.source(db).value;
        if let ast::StructKind::Record(_) = node.kind() {
            return None;
        };

        let mut params = vec![];
        let mut parameter_types = vec![];
        for field in st.fields(db).into_iter() {
            let ty = field.signature_ty(db);
            let raw_param = format!("{}", ty.display(db));

            if let Some(param_type) = raw_param.split(':').nth(1).and_then(|it| it.get(1..)) {
                parameter_types.push(param_type.to_string());
            } else {
                // useful when you have tuple struct
                parameter_types.push(raw_param.clone());
            }
            params.push(raw_param);
        }

        Some(
            FunctionSignature {
                kind: CallableKind::StructConstructor,
                visibility: node.visibility().map(|n| n.syntax().text().to_string()),
                // Do we need `const`?
                qualifier: Default::default(),
                name: node.name().map(|n| n.text().to_string()),
                ret_type: node.name().map(|n| n.text().to_string()),
                parameters: params,
                parameter_names: vec![],
                parameter_types,
                generic_parameters: generic_parameters(&node),
                where_predicates: where_predicates(&node),
                doc: None,
                has_self_param: false,
            }
            .with_doc_opt(st.docs(db)),
        )
    }

    pub(crate) fn from_enum_variant(db: &RootDatabase, variant: hir::EnumVariant) -> Option<Self> {
        let node: ast::EnumVariant = variant.source(db).value;
        match node.kind() {
            ast::StructKind::Record(_) | ast::StructKind::Unit => return None,
            _ => (),
        };

        let parent_name = variant.parent_enum(db).name(db).to_string();

        let name = format!("{}::{}", parent_name, variant.name(db));

        let mut params = vec![];
        let mut parameter_types = vec![];
        for field in variant.fields(db).into_iter() {
            let ty = field.signature_ty(db);
            let raw_param = format!("{}", ty.display(db));
            if let Some(param_type) = raw_param.split(':').nth(1).and_then(|it| it.get(1..)) {
                parameter_types.push(param_type.to_string());
            } else {
                // The unwrap_or_else is useful when you have tuple
                parameter_types.push(raw_param);
            }
            let name = field.name(db);

            params.push(format!("{}: {}", name, ty.display(db)));
        }

        Some(
            FunctionSignature {
                kind: CallableKind::VariantConstructor,
                visibility: None,
                // Do we need `const`?
                qualifier: Default::default(),
                name: Some(name),
                ret_type: None,
                parameters: params,
                parameter_names: vec![],
                parameter_types,
                generic_parameters: vec![],
                where_predicates: vec![],
                doc: None,
                has_self_param: false,
            }
            .with_doc_opt(variant.docs(db)),
        )
    }

    pub(crate) fn from_macro(db: &RootDatabase, macro_def: hir::MacroDef) -> Option<Self> {
        let node: ast::MacroCall = macro_def.source(db).value;

        let params = vec![];

        Some(
            FunctionSignature {
                kind: CallableKind::Macro,
                visibility: None,
                qualifier: Default::default(),
                name: node.name().map(|n| n.text().to_string()),
                ret_type: None,
                parameters: params,
                parameter_names: vec![],
                parameter_types: vec![],
                generic_parameters: vec![],
                where_predicates: vec![],
                doc: None,
                has_self_param: false,
            }
            .with_doc_opt(macro_def.docs(db)),
        )
    }
}

impl From<&'_ ast::FnDef> for FunctionSignature {
    fn from(node: &ast::FnDef) -> FunctionSignature {
        fn param_list(node: &ast::FnDef) -> (bool, Vec<String>, Vec<String>) {
            let mut res = vec![];
            let mut res_types = vec![];
            let mut has_self_param = false;
            if let Some(param_list) = node.param_list() {
                if let Some(self_param) = param_list.self_param() {
                    has_self_param = true;
                    let raw_param = self_param.syntax().text().to_string();

                    res_types.push(
                        raw_param
                            .split(':')
                            .nth(1)
                            .and_then(|it| it.get(1..))
                            .unwrap_or_else(|| "Self")
                            .to_string(),
                    );
                    res.push(raw_param);
                }

                res.extend(param_list.params().map(|param| param.syntax().text().to_string()));
                res_types.extend(param_list.params().map(|param| {
                    let param_text = param.syntax().text().to_string();
                    match param_text.split(':').nth(1).and_then(|it| it.get(1..)) {
                        Some(it) => it.to_string(),
                        None => param_text,
                    }
                }));
            }
            (has_self_param, res, res_types)
        }

        fn param_name_list(node: &ast::FnDef) -> Vec<String> {
            let mut res = vec![];
            if let Some(param_list) = node.param_list() {
                if let Some(self_param) = param_list.self_param() {
                    res.push(self_param.syntax().text().to_string())
                }

                res.extend(
                    param_list
                        .params()
                        .map(|param| {
                            Some(
                                param
                                    .pat()?
                                    .syntax()
                                    .descendants()
                                    .find_map(ast::Name::cast)?
                                    .text()
                                    .to_string()
                                    .trim_start_matches('_')
                                    .into(),
                            )
                        })
                        .map(|param| param.unwrap_or_default()),
                );
            }
            res
        }

        let (has_self_param, parameters, parameter_types) = param_list(node);

        FunctionSignature {
            kind: CallableKind::Function,
            visibility: node.visibility().map(|n| n.syntax().text().to_string()),
            qualifier: FunctionQualifier {
                is_async: node.async_token().is_some(),
                is_const: node.const_token().is_some(),
                is_unsafe: node.unsafe_token().is_some(),
                extern_abi: node.abi().map(|n| n.to_string()),
            },
            name: node.name().map(|n| n.text().to_string()),
            ret_type: node
                .ret_type()
                .and_then(|r| r.type_ref())
                .map(|n| n.syntax().text().to_string()),
            parameters,
            parameter_names: param_name_list(node),
            parameter_types,
            generic_parameters: generic_parameters(node),
            where_predicates: where_predicates(node),
            // docs are processed separately
            doc: None,
            has_self_param,
        }
    }
}

impl Display for FunctionSignature {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(t) = &self.visibility {
            write!(f, "{} ", t)?;
        }

        if self.qualifier.is_async {
            write!(f, "async ")?;
        }

        if self.qualifier.is_const {
            write!(f, "const ")?;
        }

        if self.qualifier.is_unsafe {
            write!(f, "unsafe ")?;
        }

        if let Some(extern_abi) = &self.qualifier.extern_abi {
            // Keyword `extern` is included in the string.
            write!(f, "{} ", extern_abi)?;
        }

        if let Some(name) = &self.name {
            match self.kind {
                CallableKind::Function => write!(f, "fn {}", name)?,
                CallableKind::StructConstructor => write!(f, "struct {}", name)?,
                CallableKind::VariantConstructor => write!(f, "{}", name)?,
                CallableKind::Macro => write!(f, "{}!", name)?,
            }
        }

        if !self.generic_parameters.is_empty() {
            write!(f, "{}", self.generic_parameters.iter().sep_by(", ").surround_with("<", ">"))?;
        }

        write!(f, "{}", self.parameters.iter().sep_by(", ").surround_with("(", ")"))?;

        if let Some(t) = &self.ret_type {
            write!(f, " -> {}", t)?;
        }

        if !self.where_predicates.is_empty() {
            write!(f, "\nwhere {}", self.where_predicates.iter().sep_by(",\n      "))?;
        }

        Ok(())
    }
}
<|endoftext|>