<commit_before>use std::char::from_u32;
use std::env;
use std::error;
use std::ffi::{OsStr, OsString};
use std::fmt;
use std::fs;
use std::io;
use std::io::Write;
use std::path::Path;
use std::process::{Command, ExitStatus};
use std::str;

use rand::random;

pub fn ensure_dir_exists<P: AsRef<Path>, F: FnOnce(&Path)>(
    path: P,
    callback: F,
) -> io::Result<bool> {
    if !is_directory(path.as_ref()) {
        callback(path.as_ref());
        fs::create_dir_all(path.as_ref()).map(|()| true)
    } else {
        Ok(false)
    }
}

pub fn is_directory<P: AsRef<Path>>(path: P) -> bool {
    fs::metadata(path).ok().as_ref().map(fs::Metadata::is_dir) == Some(true)
}

pub fn is_file<P: AsRef<Path>>(path: P) -> bool {
    fs::metadata(path).ok().as_ref().map(fs::Metadata::is_file) == Some(true)
}

pub fn path_exists<P: AsRef<Path>>(path: P) -> bool {
    fs::metadata(path).is_ok()
}

pub fn random_string(length: usize) -> String {
    let chars = b"abcdefghijklmnopqrstuvwxyz0123456789_";
    (0..length)
        .map(|_| from_u32(u32::from(chars[random::<usize>() % chars.len()])).unwrap())
        .collect()
}

pub fn if_not_empty<S: PartialEq<str>>(s: S) -> Option<S> {
    if s == *"" {
        None
    } else {
        Some(s)
    }
}

pub fn write_file(path: &Path, contents: &str) -> io::Result<()> {
    let mut file = fs::OpenOptions::new()
        .write(true)
        .truncate(true)
        .create(true)
        .open(path)?;

    io::Write::write_all(&mut file, contents.as_bytes())?;

    file.sync_data()?;

    Ok(())
}

pub fn read_file(path: &Path) -> io::Result<String> {
    let mut file = fs::OpenOptions::new().read(true).open(path)?;

    let mut contents = String::new();

    io::Read::read_to_string(&mut file, &mut contents)?;

    Ok(contents)
}

pub fn filter_file<F: FnMut(&str) -> bool>(
    src: &Path,
    dest: &Path,
    mut filter: F,
) -> io::Result<usize> {
    let src_file = fs::File::open(src)?;
    let dest_file = fs::File::create(dest)?;

    let mut reader = io::BufReader::new(src_file);
    let mut writer = io::BufWriter::new(dest_file);
    let mut removed = 0;

    for result in io::BufRead::lines(&mut reader) {
        let line = result?;
        if filter(&line) {
            writeln!(&mut writer, "{}", &line)?;
        } else {
            removed += 1;
        }
    }

    writer.flush()?;

    Ok(removed)
}

pub fn match_file<T, F: FnMut(&str) -> Option<T>>(src: &Path, mut f: F) -> io::Result<Option<T>> {
    let src_file = fs::File::open(src)?;

    let mut reader = io::BufReader::new(src_file);

    for result in io::BufRead::lines(&mut reader) {
        let line = result?;
        if let Some(r) = f(&line) {
            return Ok(Some(r));
        }
    }

    Ok(None)
}

pub fn append_file(dest: &Path, line: &str) -> io::Result<()> {
    let mut dest_file = fs::OpenOptions::new()
        .write(true)
        .append(true)
        .create(true)
        .open(dest)?;

    writeln!(&mut dest_file, "{}", line)?;

    dest_file.sync_data()?;

    Ok(())
}

pub fn tee_file<W: io::Write>(path: &Path, w: &mut W) -> io::Result<()> {
    let mut file = fs::OpenOptions::new().read(true).open(path)?;

    let buffer_size = 0x10000;
    let mut buffer = vec![0u8; buffer_size];

    loop {
        let bytes_read = io::Read::read(&mut file, &mut buffer)?;

        if bytes_read != 0 {
            io::Write::write_all(w, &buffer[0..bytes_read])?;
        } else {
            return Ok(());
        }
    }
}

pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> {
    #[cfg(windows)]
    fn symlink_dir_inner(src: &Path, dest: &Path) -> io::Result<()> {
        // std's symlink uses Windows's symlink function, which requires
        // admin. We can create directory junctions the hard way without
        // though.
        symlink_junction_inner(src, dest)
    }
    #[cfg(not(windows))]
    fn symlink_dir_inner(src: &Path, dest: &Path) -> io::Result<()> {
        ::std::os::unix::fs::symlink(src, dest)
    }

    let _ = remove_dir(dest);
    symlink_dir_inner(src, dest)
}

// Creating a directory junction on windows involves dealing with reparse
// points and the DeviceIoControl function, and this code is a skeleton of
// what can be found here:
//
// http://www.flexhex.com/docs/articles/hard-links.phtml
//
// Copied from std
#[cfg(windows)]
#[allow(non_snake_case)]
fn symlink_junction_inner(target: &Path, junction: &Path) -> io::Result<()> {
    use std::os::windows::ffi::OsStrExt;
    use std::ptr;
    use winapi::shared::minwindef::*;
    use winapi::um::fileapi::*;
    use winapi::um::ioapiset::*;
    use winapi::um::winbase::*;
    use winapi::um::winioctl::FSCTL_SET_REPARSE_POINT;
    use winapi::um::winnt::*;

    const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024;

    #[repr(C)]
    pub struct REPARSE_MOUNTPOINT_DATA_BUFFER {
        pub ReparseTag: DWORD,
        pub ReparseDataLength: DWORD,
        pub Reserved: WORD,
        pub ReparseTargetLength: WORD,
        pub ReparseTargetMaximumLength: WORD,
        pub Reserved1: WORD,
        pub ReparseTarget: WCHAR,
    }

    // We're using low-level APIs to create the junction, and these are more picky about paths.
    // For example, forward slashes cannot be used as a path separator, so we should try to
    // canonicalize the path first.
    let target = fs::canonicalize(target)?;

    fs::create_dir(junction)?;

    let path = windows::to_u16s(junction)?;

    unsafe {
        let h = CreateFileW(
            path.as_ptr(),
            GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            0 as *mut _,
            OPEN_EXISTING,
            FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
            ptr::null_mut(),
        );

        let mut data = [0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
        let db = data.as_mut_ptr() as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
        let buf = &mut (*db).ReparseTarget as *mut WCHAR;
        let mut i = 0;
        // FIXME: this conversion is very hacky
        let v = br"\??\";
        let v = v.iter().map(|x| *x as u16);
        for c in v.chain(target.as_os_str().encode_wide().skip(4)) {
            *buf.offset(i) = c;
            i += 1;
        }
        *buf.offset(i) = 0;
        i += 1;
        (*db).ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
        (*db).ReparseTargetMaximumLength = (i * 2) as WORD;
        (*db).ReparseTargetLength = ((i - 1) * 2) as WORD;
        (*db).ReparseDataLength = (*db).ReparseTargetLength as DWORD + 12;

        let mut ret = 0;
        let res = DeviceIoControl(
            h as *mut _,
            FSCTL_SET_REPARSE_POINT,
            data.as_ptr() as *mut _,
            (*db).ReparseDataLength + 8,
            ptr::null_mut(),
            0,
            &mut ret,
            ptr::null_mut(),
        );

        if res == 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(())
        }
    }
}

pub fn hardlink(src: &Path, dest: &Path) -> io::Result<()> {
    let _ = fs::remove_file(dest);
    fs::hard_link(src, dest)
}

#[derive(Debug)]
pub enum CommandError {
    Io(io::Error),
    Status(ExitStatus),
}

pub type CommandResult<T> = ::std::result::Result<T, CommandError>;

impl error::Error for CommandError {
    fn description(&self) -> &str {
        use self::CommandError::*;
        match *self {
            Io(_) => "could not execute command",
            Status(_) => "command exited with unsuccessful status",
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        use self::CommandError::*;
        match *self {
            Io(ref e) => Some(e),
            Status(_) => None,
        }
    }
}

impl fmt::Display for CommandError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            CommandError::Io(ref e) => write!(f, "Io: {}", e),
            CommandError::Status(ref s) => write!(f, "Status: {}", s),
        }
    }
}

pub fn cmd_status(cmd: &mut Command) -> CommandResult<()> {
    cmd.status().map_err(CommandError::Io).and_then(|s| {
        if s.success() {
            Ok(())
        } else {
            Err(CommandError::Status(s))
        }
    })
}

pub fn remove_dir(path: &Path) -> io::Result<()> {
    if fs::symlink_metadata(path)?.file_type().is_symlink() {
        if cfg!(windows) {
            fs::remove_dir(path)
        } else {
            fs::remove_file(path)
        }
    } else {
        // Again because remove_dir all doesn't delete write-only files on windows,
        // this is a custom implementation, more-or-less copied from cargo.
        // cc rust-lang/rust#31944
        // cc https://github.com/rust-lang/cargo/blob/master/tests/support/paths.rs#L52
        remove_dir_all::remove_dir_all(path)
    }
}

pub fn copy_dir(src: &Path, dest: &Path) -> io::Result<()> {
    fs::create_dir(dest)?;
    for entry in src.read_dir()? {
        let entry = entry?;
        let kind = entry.file_type()?;
        let src = entry.path();
        let dest = dest.join(entry.file_name());
        if kind.is_dir() {
            copy_dir(&src, &dest)?;
        } else {
            fs::copy(&src, &dest)?;
        }
    }
    Ok(())
}

pub fn prefix_arg<S: AsRef<OsStr>>(name: &str, s: S) -> OsString {
    let mut arg = OsString::from(name);
    arg.push(s);
    arg
}

pub fn has_cmd(cmd: &str) -> bool {
    let cmd = format!("{}{}", cmd, env::consts::EXE_SUFFIX);
    let path = env::var_os("PATH").unwrap_or_default();
    env::split_paths(&path)
        .map(|p| p.join(&cmd))
        .any(|p| p.exists())
}

pub fn find_cmd<'a>(cmds: &[&'a str]) -> Option<&'a str> {
    cmds.iter().cloned().find(|&s| has_cmd(s))
}

pub fn open_browser(path: &Path) -> io::Result<bool> {
    #[cfg(not(windows))]
    fn inner(path: &Path) -> io::Result<bool> {
        use std::env;
        use std::process::Stdio;

        let env_browser = env::var_os("BROWSER").map(|b| env::split_paths(&b).collect::<Vec<_>>());
        let env_commands: Vec<&str> = env_browser
            .as_ref()
            .map(|cmds| cmds.iter().by_ref().filter_map(|b| b.to_str()).collect())
            .unwrap_or_default();

        let commands = [
            "xdg-open",
            "open",
            "firefox",
            "chromium",
            "sensible-browser",
        ];
        if let Some(cmd) = find_cmd(&env_commands).or_else(|| find_cmd(&commands)) {
            Command::new(cmd)
                .arg(path)
                .stdin(Stdio::null())
                .stdout(Stdio::null())
                .stderr(Stdio::null())
                .spawn()
                .map(|_| true)
        } else {
            Ok(false)
        }
    }
    #[cfg(windows)]
    fn inner(path: &Path) -> io::Result<bool> {
        use std::ptr;
        use winapi::ctypes;
        use winapi::shared::minwindef::HINSTANCE;
        use winapi::shared::ntdef::LPCWSTR;
        use winapi::shared::windef::HWND;

        // FIXME: When winapi has this function, use their version
        extern "system" {
            pub fn ShellExecuteW(
                hwnd: HWND,
                lpOperation: LPCWSTR,
                lpFile: LPCWSTR,
                lpParameters: LPCWSTR,
                lpDirectory: LPCWSTR,
                nShowCmd: ctypes::c_int,
            ) -> HINSTANCE;
        }
        const SW_SHOW: ctypes::c_int = 5;

        let path = windows::to_u16s(path)?;
        let operation = windows::to_u16s("open")?;
        let result = unsafe {
            ShellExecuteW(
                ptr::null_mut(),
                operation.as_ptr(),
                path.as_ptr(),
                ptr::null(),
                ptr::null(),
                SW_SHOW,
            )
        };
        Ok(result as usize > 32)
    }
    inner(path)
}

#[cfg(windows)]
pub mod windows {
    use std::ffi::OsStr;
    use std::io;
    use std::os::windows::ffi::OsStrExt;

    pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
        fn inner(s: &OsStr) -> io::Result<Vec<u16>> {
            let mut maybe_result: Vec<u16> = s.encode_wide().collect();
            if maybe_result.iter().any(|&u| u == 0) {
                return Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    "strings passed to WinAPI cannot contain NULs",
                ));
            }
            maybe_result.push(0);
            Ok(maybe_result)
        }
        inner(s.as_ref())
    }
}
<commit_msg>Make truly random string<commit_after>use std::env;
use std::error;
use std::ffi::{OsStr, OsString};
use std::fmt;
use std::fs;
use std::io;
use std::io::Write;
use std::path::Path;
use std::process::{Command, ExitStatus};
use std::str;

pub fn ensure_dir_exists<P: AsRef<Path>, F: FnOnce(&Path)>(
    path: P,
    callback: F,
) -> io::Result<bool> {
    if !is_directory(path.as_ref()) {
        callback(path.as_ref());
        fs::create_dir_all(path.as_ref()).map(|()| true)
    } else {
        Ok(false)
    }
}

pub fn is_directory<P: AsRef<Path>>(path: P) -> bool {
    fs::metadata(path).ok().as_ref().map(fs::Metadata::is_dir) == Some(true)
}

pub fn is_file<P: AsRef<Path>>(path: P) -> bool {
    fs::metadata(path).ok().as_ref().map(fs::Metadata::is_file) == Some(true)
}

pub fn path_exists<P: AsRef<Path>>(path: P) -> bool {
    fs::metadata(path).is_ok()
}

pub fn random_string(length: usize) -> String {
    use rand::Rng;
    const CHARSET: &[u8] = b"abcdefghijklmnopqrstuvwxyz0123456789_";
    let mut rng = rand::thread_rng();
    (0..length)
        .map(|_| char::from(CHARSET[rng.gen_range(0, CHARSET.len())]))
        .collect()
}

pub fn if_not_empty<S: PartialEq<str>>(s: S) -> Option<S> {
    if s == *"" {
        None
    } else {
        Some(s)
    }
}

pub fn write_file(path: &Path, contents: &str) -> io::Result<()> {
    let mut file = fs::OpenOptions::new()
        .write(true)
        .truncate(true)
        .create(true)
        .open(path)?;

    io::Write::write_all(&mut file, contents.as_bytes())?;

    file.sync_data()?;

    Ok(())
}

pub fn read_file(path: &Path) -> io::Result<String> {
    let mut file = fs::OpenOptions::new().read(true).open(path)?;

    let mut contents = String::new();

    io::Read::read_to_string(&mut file, &mut contents)?;

    Ok(contents)
}

pub fn filter_file<F: FnMut(&str) -> bool>(
    src: &Path,
    dest: &Path,
    mut filter: F,
) -> io::Result<usize> {
    let src_file = fs::File::open(src)?;
    let dest_file = fs::File::create(dest)?;

    let mut reader = io::BufReader::new(src_file);
    let mut writer = io::BufWriter::new(dest_file);
    let mut removed = 0;

    for result in io::BufRead::lines(&mut reader) {
        let line = result?;
        if filter(&line) {
            writeln!(&mut writer, "{}", &line)?;
        } else {
            removed += 1;
        }
    }

    writer.flush()?;

    Ok(removed)
}

pub fn match_file<T, F: FnMut(&str) -> Option<T>>(src: &Path, mut f: F) -> io::Result<Option<T>> {
    let src_file = fs::File::open(src)?;

    let mut reader = io::BufReader::new(src_file);

    for result in io::BufRead::lines(&mut reader) {
        let line = result?;
        if let Some(r) = f(&line) {
            return Ok(Some(r));
        }
    }

    Ok(None)
}

pub fn append_file(dest: &Path, line: &str) -> io::Result<()> {
    let mut dest_file = fs::OpenOptions::new()
        .write(true)
        .append(true)
        .create(true)
        .open(dest)?;

    writeln!(&mut dest_file, "{}", line)?;

    dest_file.sync_data()?;

    Ok(())
}

pub fn tee_file<W: io::Write>(path: &Path, w: &mut W) -> io::Result<()> {
    let mut file = fs::OpenOptions::new().read(true).open(path)?;

    let buffer_size = 0x10000;
    let mut buffer = vec![0u8; buffer_size];

    loop {
        let bytes_read = io::Read::read(&mut file, &mut buffer)?;

        if bytes_read != 0 {
            io::Write::write_all(w, &buffer[0..bytes_read])?;
        } else {
            return Ok(());
        }
    }
}

pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> {
    #[cfg(windows)]
    fn symlink_dir_inner(src: &Path, dest: &Path) -> io::Result<()> {
        // std's symlink uses Windows's symlink function, which requires
        // admin. We can create directory junctions the hard way without
        // though.
        symlink_junction_inner(src, dest)
    }
    #[cfg(not(windows))]
    fn symlink_dir_inner(src: &Path, dest: &Path) -> io::Result<()> {
        ::std::os::unix::fs::symlink(src, dest)
    }

    let _ = remove_dir(dest);
    symlink_dir_inner(src, dest)
}

// Creating a directory junction on windows involves dealing with reparse
// points and the DeviceIoControl function, and this code is a skeleton of
// what can be found here:
//
// http://www.flexhex.com/docs/articles/hard-links.phtml
//
// Copied from std
#[cfg(windows)]
#[allow(non_snake_case)]
fn symlink_junction_inner(target: &Path, junction: &Path) -> io::Result<()> {
    use std::os::windows::ffi::OsStrExt;
    use std::ptr;
    use winapi::shared::minwindef::*;
    use winapi::um::fileapi::*;
    use winapi::um::ioapiset::*;
    use winapi::um::winbase::*;
    use winapi::um::winioctl::FSCTL_SET_REPARSE_POINT;
    use winapi::um::winnt::*;

    const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024;

    #[repr(C)]
    pub struct REPARSE_MOUNTPOINT_DATA_BUFFER {
        pub ReparseTag: DWORD,
        pub ReparseDataLength: DWORD,
        pub Reserved: WORD,
        pub ReparseTargetLength: WORD,
        pub ReparseTargetMaximumLength: WORD,
        pub Reserved1: WORD,
        pub ReparseTarget: WCHAR,
    }

    // We're using low-level APIs to create the junction, and these are more picky about paths.
    // For example, forward slashes cannot be used as a path separator, so we should try to
    // canonicalize the path first.
    let target = fs::canonicalize(target)?;

    fs::create_dir(junction)?;

    let path = windows::to_u16s(junction)?;

    unsafe {
        let h = CreateFileW(
            path.as_ptr(),
            GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            0 as *mut _,
            OPEN_EXISTING,
            FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
            ptr::null_mut(),
        );

        let mut data = [0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
        let db = data.as_mut_ptr() as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
        let buf = &mut (*db).ReparseTarget as *mut WCHAR;
        let mut i = 0;
        // FIXME: this conversion is very hacky
        let v = br"\??\";
        let v = v.iter().map(|x| *x as u16);
        for c in v.chain(target.as_os_str().encode_wide().skip(4)) {
            *buf.offset(i) = c;
            i += 1;
        }
        *buf.offset(i) = 0;
        i += 1;
        (*db).ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
        (*db).ReparseTargetMaximumLength = (i * 2) as WORD;
        (*db).ReparseTargetLength = ((i - 1) * 2) as WORD;
        (*db).ReparseDataLength = (*db).ReparseTargetLength as DWORD + 12;

        let mut ret = 0;
        let res = DeviceIoControl(
            h as *mut _,
            FSCTL_SET_REPARSE_POINT,
            data.as_ptr() as *mut _,
            (*db).ReparseDataLength + 8,
            ptr::null_mut(),
            0,
            &mut ret,
            ptr::null_mut(),
        );

        if res == 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(())
        }
    }
}

pub fn hardlink(src: &Path, dest: &Path) -> io::Result<()> {
    let _ = fs::remove_file(dest);
    fs::hard_link(src, dest)
}

#[derive(Debug)]
pub enum CommandError {
    Io(io::Error),
    Status(ExitStatus),
}

pub type CommandResult<T> = ::std::result::Result<T, CommandError>;

impl error::Error for CommandError {
    fn description(&self) -> &str {
        use self::CommandError::*;
        match *self {
            Io(_) => "could not execute command",
            Status(_) => "command exited with unsuccessful status",
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        use self::CommandError::*;
        match *self {
            Io(ref e) => Some(e),
            Status(_) => None,
        }
    }
}

impl fmt::Display for CommandError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            CommandError::Io(ref e) => write!(f, "Io: {}", e),
            CommandError::Status(ref s) => write!(f, "Status: {}", s),
        }
    }
}

pub fn cmd_status(cmd: &mut Command) -> CommandResult<()> {
    cmd.status().map_err(CommandError::Io).and_then(|s| {
        if s.success() {
            Ok(())
        } else {
            Err(CommandError::Status(s))
        }
    })
}

pub fn remove_dir(path: &Path) -> io::Result<()> {
    if fs::symlink_metadata(path)?.file_type().is_symlink() {
        if cfg!(windows) {
            fs::remove_dir(path)
        } else {
            fs::remove_file(path)
        }
    } else {
        // Again because remove_dir all doesn't delete write-only files on windows,
        // this is a custom implementation, more-or-less copied from cargo.
        // cc rust-lang/rust#31944
        // cc https://github.com/rust-lang/cargo/blob/master/tests/support/paths.rs#L52
        remove_dir_all::remove_dir_all(path)
    }
}

pub fn copy_dir(src: &Path, dest: &Path) -> io::Result<()> {
    fs::create_dir(dest)?;
    for entry in src.read_dir()? {
        let entry = entry?;
        let kind = entry.file_type()?;
        let src = entry.path();
        let dest = dest.join(entry.file_name());
        if kind.is_dir() {
            copy_dir(&src, &dest)?;
        } else {
            fs::copy(&src, &dest)?;
        }
    }
    Ok(())
}

pub fn prefix_arg<S: AsRef<OsStr>>(name: &str, s: S) -> OsString {
    let mut arg = OsString::from(name);
    arg.push(s);
    arg
}

pub fn has_cmd(cmd: &str) -> bool {
    let cmd = format!("{}{}", cmd, env::consts::EXE_SUFFIX);
    let path = env::var_os("PATH").unwrap_or_default();
    env::split_paths(&path)
        .map(|p| p.join(&cmd))
        .any(|p| p.exists())
}

pub fn find_cmd<'a>(cmds: &[&'a str]) -> Option<&'a str> {
    cmds.iter().cloned().find(|&s| has_cmd(s))
}

pub fn open_browser(path: &Path) -> io::Result<bool> {
    #[cfg(not(windows))]
    fn inner(path: &Path) -> io::Result<bool> {
        use std::env;
        use std::process::Stdio;

        let env_browser = env::var_os("BROWSER").map(|b| env::split_paths(&b).collect::<Vec<_>>());
        let env_commands: Vec<&str> = env_browser
            .as_ref()
            .map(|cmds| cmds.iter().by_ref().filter_map(|b| b.to_str()).collect())
            .unwrap_or_default();

        let commands = [
            "xdg-open",
            "open",
            "firefox",
            "chromium",
            "sensible-browser",
        ];
        if let Some(cmd) = find_cmd(&env_commands).or_else(|| find_cmd(&commands)) {
            Command::new(cmd)
                .arg(path)
                .stdin(Stdio::null())
                .stdout(Stdio::null())
                .stderr(Stdio::null())
                .spawn()
                .map(|_| true)
        } else {
            Ok(false)
        }
    }
    #[cfg(windows)]
    fn inner(path: &Path) -> io::Result<bool> {
        use std::ptr;
        use winapi::ctypes;
        use winapi::shared::minwindef::HINSTANCE;
        use winapi::shared::ntdef::LPCWSTR;
        use winapi::shared::windef::HWND;

        // FIXME: When winapi has this function, use their version
        extern "system" {
            pub fn ShellExecuteW(
                hwnd: HWND,
                lpOperation: LPCWSTR,
                lpFile: LPCWSTR,
                lpParameters: LPCWSTR,
                lpDirectory: LPCWSTR,
                nShowCmd: ctypes::c_int,
            ) -> HINSTANCE;
        }
        const SW_SHOW: ctypes::c_int = 5;

        let path = windows::to_u16s(path)?;
        let operation = windows::to_u16s("open")?;
        let result = unsafe {
            ShellExecuteW(
                ptr::null_mut(),
                operation.as_ptr(),
                path.as_ptr(),
                ptr::null(),
                ptr::null(),
                SW_SHOW,
            )
        };
        Ok(result as usize > 32)
    }
    inner(path)
}

#[cfg(windows)]
pub mod windows {
    use std::ffi::OsStr;
    use std::io;
    use std::os::windows::ffi::OsStrExt;

    pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
        fn inner(s: &OsStr) -> io::Result<Vec<u16>> {
            let mut maybe_result: Vec<u16> = s.encode_wide().collect();
            if maybe_result.iter().any(|&u| u == 0) {
                return Err(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    "strings passed to WinAPI cannot contain NULs",
                ));
            }
            maybe_result.push(0);
            Ok(maybe_result)
        }
        inner(s.as_ref())
    }
}
<|endoftext|>


<commit_before>use base::vec_from_elem;
use gfx::Texture;
use gl;
use std::ptr::copy_nonoverlapping_memory;
use std::vec::Vec;
use std::io::Read;
use super::types::WadTextureHeader;

pub struct Image {
    width: usize,
    height: usize,
    x_offset: isize,
    y_offset: isize,
    pixels: Vec<u16>,
}

macro_rules! io_try(
    ($e:expr) => (try!($e.map_err(|e| String::from_str(e.desc))))
);

impl Image {
    pub fn new(width: usize, height: usize) -> Image {
        Image { width: width,
                height: height,
                x_offset: 0,
                y_offset: 0,
                pixels: vec_from_elem(width * height, 0xff00) }
    }

    pub fn new_from_header(header: &WadTextureHeader) -> Image {
        Image::new(header.width as usize, header.height as usize)
    }

    pub fn from_buffer(buffer: &[u8]) -> Image {
        let mut reader = buffer;
        let width = reader.read_le_u16().unwrap() as usize;
        let height = reader.read_le_u16().unwrap() as usize;
        let x_offset = reader.read_le_i16().unwrap() as isize;
        let y_offset = reader.read_le_i16().unwrap() as isize;

        let mut pixels = vec![-1; width * height];
        for i_column in 0 .. width {
            let column_offset = reader.read_le_u32().unwrap() as usize;
            let mut column = buffer[column_offset..].iter().cloned();
            loop {
                let row_start = match column.next().unwrap() {
                    255 => break,
                    x => x,
                };

                let run_length = column.next().unwrap();
                column.next().unwrap();
                let mut dest_idx = row_start as usize * width + i_column;
                for i in 0..run_length {
                    pixels[dest_idx] = column.next().unwrap() as u16;
                    dest_idx += width;
                }
                column.next().unwrap();
            }
        }
        let pixels = pixels;
        //// Sorry for the messy/unsafe code, but the array bounds checks in this
        //// tight loop make it 6x slower.
        //for i_column in range(0, width as isize) { unsafe {
        //    // Each column is defined as a number of vertical `runs' which are
        //    // defined starting at `offset' in the buffer.
        //    let offset = buffer.read_le_u32().unwrap() as isize;
        //    let mut src_ptr = buffer.as_ptr().offset(offset);
        //    'this_column: loop {
        //        // The first byte contains the vertical coordinate of the run's
        //        // start.
        //        let row_start = *src_ptr as isize; src_ptr = src_ptr.offset(1);

        //        // Pointer to the beginning of the run in `pixels'.
        //        let mut dest_ptr = pixels
        //            .as_mut_ptr().offset(row_start * width as isize + i_column);

        //        // The special value of 255 means this is the last run in the
        //        // column, so move on to the next one.
        //        if row_start == 255 { break 'this_column; }

        //        // The second byte is the length of this run. Skip an additional
        //        // byte which is ignored for some reason.
        //        let run_length = *src_ptr as isize; src_ptr = src_ptr.offset(2);

        //        let src_end = src_ptr.offset(run_length);  // Ptr to end of run.
        //        while src_ptr < src_end {
        //            // Copy one byte converting it into an opaque pixels (high
        //            // bits are zero) and advance the pointers.
        //            *dest_ptr = *src_ptr as u16;
        //            dest_ptr = dest_ptr.offset(width as isize);
        //            src_ptr = src_ptr.offset(1);
        //        }
        //        // And another ignored byte after the run.
        //        src_ptr = src_ptr.offset(1);
        //    }
        //}}
        //let pixels = pixels;

        Image { width: width,
                height: height,
                x_offset: x_offset,
                y_offset: y_offset,
                pixels: pixels }
    }

    pub fn blit(&mut self, source: &Image, x_offset: isize, y_offset: isize,
                ignore_transparency: bool) {
        // Figure out the region in source which is not out of bounds when
        // copied into self.
        let y_start = if y_offset < 0 { (-y_offset) as usize } else { 0 };
        let x_start = if x_offset < 0 { (-x_offset) as usize } else { 0 };
        let y_end = if self.height as isize > source.height as isize + y_offset {
            source.height
        } else {
            (self.height as isize - y_offset) as usize
        };
        let x_end = if self.width as isize > source.width as isize + x_offset {
            source.width
        } else {
            (self.width as isize - x_offset) as usize
        };

        if ignore_transparency {
            // If we don't care about transparency we can memcpy row by row.
            let src_pitch = source.width as isize;
            let dest_pitch = self.width as isize;
            let copy_width = x_end - x_start;
            let copy_height = (y_end - y_start) as isize;
            let (x_start, y_start) = (x_start as isize, y_start as isize);
            unsafe {
                let mut src_ptr = source.pixels.as_ptr().offset(
                    x_start + y_start * src_pitch);
                let mut dest_ptr = self.pixels.as_mut_ptr().offset(
                    x_start + x_offset + (y_start + y_offset) * dest_pitch);

                let src_end = src_ptr.offset(copy_height * src_pitch);
                while src_ptr < src_end {
                    copy_nonoverlapping_memory(dest_ptr, src_ptr, copy_width);
                    src_ptr = src_ptr.offset(src_pitch);
                    dest_ptr = dest_ptr.offset(dest_pitch);
                }
            }
        } else {
            // Only copy pixels whose high bits are not set.
            let dest_ptr = self.pixels.as_mut_ptr();
            let src_ptr = source.pixels.as_ptr();
            for src_y in range(y_start, y_end) {
                let dest_y = (src_y as isize + y_offset) as usize;
                for src_x in range(x_start, x_end) {
                    let dest_x = (src_x as isize + x_offset) as usize;

                    let (dest_x, dest_y) = (dest_x as usize, dest_y as usize);
                    let dest_index = (dest_x + dest_y * self.width) as isize;
                    let src_index = (src_x + src_y * source.width) as isize;

                    unsafe {
                        // `Blending' is a simple copy/no copy, but using bit
                        // ops we can avoid branching.
                        let src_pixel = *src_ptr.offset(src_index);
                        let dest_pixel = dest_ptr.offset(dest_index);
                        let blend = (0.wrapping_sub(src_pixel >> 15)) as u16;
                        *dest_pixel = (src_pixel & !blend) |
                                      (*dest_pixel & blend);
                    }
                }
            }
        }
    }

    pub fn to_texture(&self) -> Texture {
        let mut tex = Texture::new(gl::TEXTURE_2D);
        tex.bind(gl::TEXTURE0);
        tex.set_filters_nearest()
           .data_rg_u8(0, self.width, self.height, &self.pixels)
           .unbind(gl::TEXTURE0);
        tex
    }

    pub fn x_offset(&self) -> isize { self.x_offset }
    pub fn y_offset(&self) -> isize { self.y_offset }

    pub fn width(&self) -> usize { self.width }
    pub fn height(&self) -> usize { self.height }

    pub fn num_pixels(&self) -> usize { self.pixels.len() }

    pub fn get_pixels(&self) -> &[u16] { &self.pixels }

}

<commit_msg>Fixed all rustup errors. Many warnings remain.<commit_after>use base::vec_from_elem;
use gfx::Texture;
use gl;
use std::ptr::copy_nonoverlapping_memory;
use std::vec::Vec;
use super::types::WadTextureHeader;

pub struct Image {
    width: usize,
    height: usize,
    x_offset: isize,
    y_offset: isize,
    pixels: Vec<u16>,
}

macro_rules! io_try(
    ($e:expr) => (try!($e.map_err(|e| String::from_str(e.desc))))
);

impl Image {
    pub fn new(width: usize, height: usize) -> Image {
        Image { width: width,
                height: height,
                x_offset: 0,
                y_offset: 0,
                pixels: vec_from_elem(width * height, 0xff00) }
    }

    pub fn new_from_header(header: &WadTextureHeader) -> Image {
        Image::new(header.width as usize, header.height as usize)
    }

    pub fn from_buffer(buffer: &[u8]) -> Image {
        let mut reader = buffer;
        let width = reader.read_le_u16().unwrap() as usize;
        let height = reader.read_le_u16().unwrap() as usize;
        let x_offset = reader.read_le_i16().unwrap() as isize;
        let y_offset = reader.read_le_i16().unwrap() as isize;

        let mut pixels = vec![-1; width * height];
        // Sorry for the messy/unsafe code, but the array bounds checks in this
        // tight loop make it 6x slower.
        for i_column in range(0, width as isize) { unsafe {
            // Each column is defined as a number of vertical `runs' which are
            // defined starting at `offset' in the buffer.
            let offset = reader.read_le_u32().unwrap() as isize;
            let mut src_ptr = buffer.as_ptr().offset(offset);
            'this_column: loop {
                // The first byte contains the vertical coordinate of the run's
                // start.
                let row_start = *src_ptr as isize; src_ptr = src_ptr.offset(1);

                // Pointer to the beginning of the run in `pixels'.
                let mut dest_ptr = pixels
                    .as_mut_ptr().offset(row_start * width as isize + i_column);

                // The special value of 255 means this is the last run in the
                // column, so move on to the next one.
                if row_start == 255 { break 'this_column; }

                // The second byte is the length of this run. Skip an additional
                // byte which is ignored for some reason.
                let run_length = *src_ptr as isize; src_ptr = src_ptr.offset(2);

                let src_end = src_ptr.offset(run_length);  // Ptr to end of run.
                while src_ptr < src_end {
                    // Copy one byte converting it into an opaque pixels (high
                    // bits are zero) and advance the pointers.
                    *dest_ptr = *src_ptr as u16;
                    dest_ptr = dest_ptr.offset(width as isize);
                    src_ptr = src_ptr.offset(1);
                }
                // And another ignored byte after the run.
                src_ptr = src_ptr.offset(1);
            }
        }}
        let pixels = pixels;

        Image { width: width,
                height: height,
                x_offset: x_offset,
                y_offset: y_offset,
                pixels: pixels }
    }

    pub fn blit(&mut self, source: &Image, x_offset: isize, y_offset: isize,
                ignore_transparency: bool) {
        // Figure out the region in source which is not out of bounds when
        // copied into self.
        let y_start = if y_offset < 0 { (-y_offset) as usize } else { 0 };
        let x_start = if x_offset < 0 { (-x_offset) as usize } else { 0 };
        let y_end = if self.height as isize > source.height as isize + y_offset {
            source.height
        } else {
            (self.height as isize - y_offset) as usize
        };
        let x_end = if self.width as isize > source.width as isize + x_offset {
            source.width
        } else {
            (self.width as isize - x_offset) as usize
        };

        if ignore_transparency {
            // If we don't care about transparency we can memcpy row by row.
            let src_pitch = source.width as isize;
            let dest_pitch = self.width as isize;
            let copy_width = x_end - x_start;
            let copy_height = (y_end - y_start) as isize;
            let (x_start, y_start) = (x_start as isize, y_start as isize);
            unsafe {
                let mut src_ptr = source.pixels.as_ptr().offset(
                    x_start + y_start * src_pitch);
                let mut dest_ptr = self.pixels.as_mut_ptr().offset(
                    x_start + x_offset + (y_start + y_offset) * dest_pitch);

                let src_end = src_ptr.offset(copy_height * src_pitch);
                while src_ptr < src_end {
                    copy_nonoverlapping_memory(dest_ptr, src_ptr, copy_width);
                    src_ptr = src_ptr.offset(src_pitch);
                    dest_ptr = dest_ptr.offset(dest_pitch);
                }
            }
        } else {
            // Only copy pixels whose high bits are not set.
            let dest_ptr = self.pixels.as_mut_ptr();
            let src_ptr = source.pixels.as_ptr();
            for src_y in range(y_start, y_end) {
                let dest_y = (src_y as isize + y_offset) as usize;
                for src_x in range(x_start, x_end) {
                    let dest_x = (src_x as isize + x_offset) as usize;

                    let (dest_x, dest_y) = (dest_x as usize, dest_y as usize);
                    let dest_index = (dest_x + dest_y * self.width) as isize;
                    let src_index = (src_x + src_y * source.width) as isize;

                    unsafe {
                        // `Blending' is a simple copy/no copy, but using bit
                        // ops we can avoid branching.
                        let src_pixel = *src_ptr.offset(src_index);
                        let dest_pixel = dest_ptr.offset(dest_index);
                        let blend = (0.wrapping_sub(src_pixel >> 15)) as u16;
                        *dest_pixel = (src_pixel & !blend) |
                                      (*dest_pixel & blend);
                    }
                }
            }
        }
    }

    pub fn to_texture(&self) -> Texture {
        let mut tex = Texture::new(gl::TEXTURE_2D);
        tex.bind(gl::TEXTURE0);
        tex.set_filters_nearest()
           .data_rg_u8(0, self.width, self.height, &self.pixels)
           .unbind(gl::TEXTURE0);
        tex
    }

    pub fn x_offset(&self) -> isize { self.x_offset }
    pub fn y_offset(&self) -> isize { self.y_offset }

    pub fn width(&self) -> usize { self.width }
    pub fn height(&self) -> usize { self.height }

    pub fn num_pixels(&self) -> usize { self.pixels.len() }

    pub fn get_pixels(&self) -> &[u16] { &self.pixels }
}

<|endoftext|>


<commit_before>use failure::{Error, Fail, bail, ensure};

use super::util;
use super::loader;
use super::arch::{Arch};
use super::loader::{LoadedModule, Loader};

#[derive(Debug, Fail)]
pub enum WorkspaceError {
    #[fail(display = "The given buffer is not supported (arch/plat/file format)")]
    NotSupported,
}

pub struct Workspace<A: Arch> {
    // name or source of the file
    pub filename: String,
    // raw bytes of the file
    pub buf: Vec<u8>,

    pub loader: Box<dyn Loader<A>>,
    pub module: LoadedModule<A>,

    // analysis {
    //   flowmeta,
    //   datameta,
    //   symbols,
    //   functions,
    // }
}

impl<A: Arch + 'static> Workspace<A> {
    pub fn from_bytes(filename: &str, buf: Vec<u8>) -> Result<Workspace<A>, Error> {
        ensure!(A::get_bits() == 32, "only 32-bit loading right now");

        let (ldr, module) = loader::load::<A>(&buf)?;

        Ok(Workspace::<A>{
            filename: filename.to_string(),
            buf: buf,
            loader: ldr,
            module: module,
        })
    }

    pub fn from_file(filename: &str) -> Result<Workspace<A>, Error> {
        let buf = util::read_file(filename)?;
        Workspace::from_bytes(filename, buf)
    }

    // API:
    //   get_insn
    //   get_byte/word/dword
    //   get_xrefs_to
    //   get_xrefs_from
    //   get_functions

    // elsewhere:
    //   call graph
    //   control flow graph
}
<commit_msg>workspace: begin to implement from_bytes<commit_after>use failure::{Error, Fail, bail, ensure};

use super::util;
use super::loader;
use super::arch::{Arch};
use super::loader::{LoadedModule, Loader};

#[derive(Debug, Fail)]
pub enum WorkspaceError {
    #[fail(display = "The given buffer is not supported (arch/plat/file format)")]
    NotSupported,
}

pub struct Workspace<A: Arch> {
    // name or source of the file
    pub filename: String,
    // raw bytes of the file
    pub buf: Vec<u8>,

    pub loader: Box<dyn Loader<A>>,
    pub module: LoadedModule<A>,

    // analysis {
    //   flowmeta,
    //   datameta,
    //   symbols,
    //   functions,
    // }
}

impl<A: Arch + 'static> Workspace<A> {
    /// Create a workspace and load the given bytes.
    ///
    /// Example:
    ///
    /// ```
    /// use lancelot::arch::*;
    /// use lancelot::workspace::Workspace;
    ///
    /// Workspace::<Arch32>::from_bytes("foo.bin", b"\xEB\xFE")
    ///   .map(|ws| {
    ///     assert_eq!(ws.loader.get_name(),       "Windows/32/Raw");
    ///     assert_eq!(ws.module.base_address,     0x0);
    ///     assert_eq!(ws.module.sections[0].name, "raw");
    ///   })
    ///   .map_err(|e| panic!(e));
    /// ```
    pub fn from_bytes(filename: &str, buf: &[u8]) -> Result<Workspace<A>, Error> {
        let buf = buf.to_vec();
        let (ldr, module) = loader::load::<A>(&buf)?;

        Ok(Workspace::<A>{
            filename: filename.to_string(),
            buf: buf,
            loader: ldr,
            module: module,
        })
    }

    pub fn from_file(filename: &str) -> Result<Workspace<A>, Error> {
        let buf = util::read_file(filename)?;
        Workspace::from_bytes(filename, &buf)
    }

    // API:
    //   get_insn
    //   get_byte/word/dword
    //   get_xrefs_to
    //   get_xrefs_from
    //   get_functions

    // elsewhere:
    //   call graph
    //   control flow graph
}
<|endoftext|>


<commit_before>//
// rslex - a lexer generator for rust
//
// buffer.rs
// A lookahead buffer for input
//
// Andrei de A. Formiga, 2013-10-02
//

extern mod std;

use std::str::CharIterator;

/// Allows the use of one "lookahead" character, which can be
/// returned to the stream. Basically similar to a `Peekable`
/// iterator but with a more convenient interface
/// (for a case where peek is used all the time
///  and it almost always should advance the iterator)
struct LookaheadBuffer<'r> {
    contents: &'r str,
    iter: CharIterator<'r>,
    peek: Option<char>
}

impl<'r> LookaheadBuffer<'r> {
    pub fn new(s: &'r str) -> LookaheadBuffer<'r> {
        LookaheadBuffer { contents: s, iter: s.chars(), peek: None }
    }

    pub fn len(&self) -> uint {
        self.contents.len()
    }

    pub fn next_char(&mut self) -> Option<char> {
        match self.peek {
            None => self.iter.next(),
            Some(c) => {
                self.peek = None;
                Some(c)
            }
        }
    }

    /// Returns `c` to the character stream, to be returned as the
    /// next char. If `return_char` is called twice without an intervening
    /// `next_char`, the buffer will forget the previous returned character.
    pub fn return_char(&mut self, c: char) {
        self.peek = Some(c)
    }

    pub fn skip_whitespace(&mut self) {
        loop {
            match self.next_char() {
                None => break,
                Some(c) if !std::char::is_whitespace(c) => { self.return_char(c); break }
                Some(_) => ()
            }
        }
    }
}

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

    #[test]
    fn no_buffer_use() {
        let mut buffer = LookaheadBuffer::new("abcdef");
        assert_eq!(buffer.len(), 6);
        assert_eq!(buffer.next_char(), Some('a'));
        assert_eq!(buffer.next_char(), Some('b'));
        assert_eq!(buffer.next_char(), Some('c'));
        assert_eq!(buffer.next_char(), Some('d'));
        assert_eq!(buffer.next_char(), Some('e'));
        assert_eq!(buffer.next_char(), Some('f'));
        assert_eq!(buffer.next_char(), None);
    }

    #[test]
    fn no_buffer_use_iterator() {
        let mut iter = "abcdef".chars().peekable();
        assert_eq!(iter.next(), Some('a'));
        assert_eq!(iter.next(), Some('b'));

        match iter.peek() {
            None => fail!("Should not be none"),
            Some(c) => assert_eq!(*c, 'c')
        }

        assert_eq!(iter.next(), Some('c'));
    }

    #[test]
    fn buffer_use_return_variable() {
        let mut buffer = LookaheadBuffer::new("abcdef");
        assert_eq!(buffer.next_char(), Some('a'));
        let c = match buffer.next_char() {
            None => fail!("Should not be none"),
            Some(ch) => ch
        };

        assert_eq!(c, 'b');

        buffer.return_char(c);

        assert_eq!(buffer.next_char(), Some('b'));
    }

    #[test]
    fn buffer_use() {
        let mut buffer = LookaheadBuffer::new("abcdef");
        assert_eq!(buffer.next_char(), Some('a'));
        buffer.return_char('a');
        assert_eq!(buffer.next_char(), Some('a'));
        assert_eq!(buffer.next_char(), Some('b'));
        assert_eq!(buffer.next_char(), Some('c'));
        buffer.return_char('c');
        assert_eq!(buffer.next_char(), Some('c'));
        assert_eq!(buffer.next_char(), Some('d'));
        assert_eq!(buffer.next_char(), Some('e'));
        assert_eq!(buffer.next_char(), Some('f'));
        assert_eq!(buffer.next_char(), None);
        buffer.return_char('f');
        assert_eq!(buffer.next_char(), Some('f'));
        assert_eq!(buffer.next_char(), None);
        assert_eq!(buffer.next_char(), None);
    }

    #[test]
    fn test_skip_ws() {
        let mut buffer = LookaheadBuffer::new("   abc   ");
        buffer.skip_whitespace();
        assert_eq!(buffer.next_char(), Some('a'));
        buffer.skip_whitespace();
        assert_eq!(buffer.next_char(), Some('b'));
        buffer.skip_whitespace();
        assert_eq!(buffer.next_char(), Some('c'));
        buffer.skip_whitespace();
        assert_eq!(buffer.next_char(), None);
    }
}

<commit_msg>Implementing position tracking<commit_after>//
// rslex - a lexer generator for rust
//
// buffer.rs
// A lookahead buffer for input
//
// Andrei de A. Formiga, 2013-10-02
//

extern mod std;

use std::str::CharIterator;

/// A position in the input
struct Pos {
    /// line number (starting at 1)
    line: uint,
    /// column number (starting at 0)
    col: uint
}

impl Pos {
    pub fn start() -> Pos {
        Pos { line: 1, col: 0 }
    }

    pub fn next(&mut self, c: char) {
        if c == '\n' {
            self.line += 1;
            self.col = 0;
        }
        else {
            self.col += 1;
        }
    }
}

type CharPos = uint;

/// Allows the use of one "lookahead" character, which can be
/// returned to the stream. Basically similar to a `Peekable`
/// iterator but with a more convenient interface
/// (for a case where peek is used all the time
///  and it almost always should advance the iterator)
struct LookaheadBuffer<'r> {
    contents: &'r str,
    iter: CharIterator<'r>,
    peek: Option<char>,
    pos: CharPos
}

impl<'r> LookaheadBuffer<'r> {
    pub fn new(s: &'r str) -> LookaheadBuffer<'r> {
        LookaheadBuffer { contents: s, iter: s.chars(), peek: None, pos: 0 }
    }

    pub fn len(&self) -> uint {
        self.contents.len()
    }

    fn get_next_char(&mut self) -> Option<char> {
        match self.peek {
            None => self.iter.next(),
            Some(c) => {
                self.peek = None;
                Some(c)
            }
        }
    }

    pub fn next_char(&mut self) -> Option<char> {
        let res = self.get_next_char();
        // update position
        match res {
            Some(_) => self.pos += 1,
            None => ()
        }
        res
    }

    /// Returns `c` to the character stream, to be returned as the
    /// next char. If `return_char` is called twice without an intervening
    /// `next_char`, the buffer will forget the previous returned character.
    pub fn return_char(&mut self, c: char) {
        self.pos -= 1;
        self.peek = Some(c)
    }

    pub fn skip_whitespace(&mut self) {
        loop {
            match self.next_char() {
                None => break,
                Some(c) if !std::char::is_whitespace(c) => { self.return_char(c); break }
                Some(_) => ()
            }
        }
    }
}

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

    #[test]
    fn no_buffer_use() {
        let mut buffer = LookaheadBuffer::new("abcdef");
        assert_eq!(buffer.len(), 6);
        assert_eq!(buffer.next_char(), Some('a'));
        assert_eq!(buffer.next_char(), Some('b'));
        assert_eq!(buffer.next_char(), Some('c'));
        assert_eq!(buffer.next_char(), Some('d'));
        assert_eq!(buffer.next_char(), Some('e'));
        assert_eq!(buffer.next_char(), Some('f'));
        assert_eq!(buffer.next_char(), None);
    }

    #[test]
    fn no_buffer_use_iterator() {
        let mut iter = "abcdef".chars().peekable();
        assert_eq!(iter.next(), Some('a'));
        assert_eq!(iter.next(), Some('b'));

        match iter.peek() {
            None => fail!("Should not be none"),
            Some(c) => assert_eq!(*c, 'c')
        }

        assert_eq!(iter.next(), Some('c'));
    }

    #[test]
    fn buffer_use_return_variable() {
        let mut buffer = LookaheadBuffer::new("abcdef");
        assert_eq!(buffer.next_char(), Some('a'));
        let c = match buffer.next_char() {
            None => fail!("Should not be none"),
            Some(ch) => ch
        };

        assert_eq!(c, 'b');

        buffer.return_char(c);

        assert_eq!(buffer.next_char(), Some('b'));
    }

    #[test]
    fn buffer_use() {
        let mut buffer = LookaheadBuffer::new("abcdef");
        assert_eq!(buffer.next_char(), Some('a'));
        buffer.return_char('a');
        assert_eq!(buffer.next_char(), Some('a'));
        assert_eq!(buffer.next_char(), Some('b'));
        assert_eq!(buffer.next_char(), Some('c'));
        buffer.return_char('c');
        assert_eq!(buffer.next_char(), Some('c'));
        assert_eq!(buffer.next_char(), Some('d'));
        assert_eq!(buffer.next_char(), Some('e'));
        assert_eq!(buffer.next_char(), Some('f'));
        assert_eq!(buffer.next_char(), None);
        buffer.return_char('f');
        assert_eq!(buffer.next_char(), Some('f'));
        assert_eq!(buffer.next_char(), None);
        assert_eq!(buffer.next_char(), None);
    }

    #[test]
    fn test_skip_ws() {
        let mut buffer = LookaheadBuffer::new("   abc   ");
        buffer.skip_whitespace();
        assert_eq!(buffer.next_char(), Some('a'));
        buffer.skip_whitespace();
        assert_eq!(buffer.next_char(), Some('b'));
        buffer.skip_whitespace();
        assert_eq!(buffer.next_char(), Some('c'));
        buffer.skip_whitespace();
        assert_eq!(buffer.next_char(), None);
    }

    #[test]
    fn position() {
        let mut buffer = LookaheadBuffer::new("   abc   ");
        assert_eq!(buffer.pos, 0);
        buffer.skip_whitespace();
        assert_eq!(buffer.pos, 3);
        assert_eq!(buffer.next_char(), Some('a'));
        assert_eq!(buffer.pos, 4);
        assert_eq!(buffer.next_char(), Some('b'));
        assert_eq!(buffer.pos, 5);
        assert_eq!(buffer.next_char(), Some('c'));
        assert_eq!(buffer.pos, 6);
        buffer.return_char('c');
        assert_eq!(buffer.pos, 5);
        assert_eq!(buffer.next_char(), Some('c'));
        assert_eq!(buffer.pos, 6);
        buffer.skip_whitespace();
        assert_eq!(buffer.pos, 9);
    }
}

<|endoftext|>


<commit_before>use std::fmt::Write;
use std::{env, iter};

use anyhow::bail;
use xshell::{cmd, Shell};

pub(crate) fn get_changelog(
    sh: &Shell,
    changelog_n: usize,
    commit: &str,
    prev_tag: &str,
    today: &str,
) -> anyhow::Result<String> {
    let git_log = cmd!(sh, "git log {prev_tag}..HEAD --merges --reverse").read()?;
    let mut features = String::new();
    let mut fixes = String::new();
    let mut internal = String::new();
    let mut others = String::new();
    for line in git_log.lines() {
        let line = line.trim_start();
        if let Some(p) = line.find(':') {
            let pr = &line[..p];
            if let Ok(pr_num) = pr.parse::<u32>() {
                let accept = "Accept: application/vnd.github.v3+json";
                let token = match env::var("GITHUB_TOKEN") {
                    Ok(token) => token,
                    Err(_) => bail!("Please obtain a personal access token from https://github.com/settings/tokens and set the `GITHUB_TOKEN` environment variable."),
                };
                let authorization = format!("Authorization: token {}", token);
                let pr_url = "https://api.github.com/repos/rust-analyzer/rust-analyzer/issues";

                // we don't use an HTTPS client or JSON parser to keep the build times low
                let pr_json =
                    cmd!(sh, "curl -s -H {accept} -H {authorization} {pr_url}/{pr}").read()?;
                let pr_title = cmd!(sh, "jq .title").stdin(&pr_json).read()?;
                let pr_title = unescape(&pr_title[1..pr_title.len() - 1]);
                let pr_comment = cmd!(sh, "jq .body").stdin(pr_json).read()?;

                let comments_json =
                    cmd!(sh, "curl -s -H {accept} -H {authorization} {pr_url}/{pr}/comments")
                        .read()?;
                let pr_comments = cmd!(sh, "jq .[].body").stdin(comments_json).read()?;

                let l = iter::once(pr_comment.as_str())
                    .chain(pr_comments.lines())
                    .rev()
                    .find_map(|it| {
                        let it = unescape(&it[1..it.len() - 1]);
                        it.lines().find_map(parse_changelog_line)
                    })
                    .into_iter()
                    .next()
                    .unwrap_or_else(|| parse_title_line(&pr_title));
                let s = match l.kind {
                    PrKind::Feature => &mut features,
                    PrKind::Fix => &mut fixes,
                    PrKind::Internal => &mut internal,
                    PrKind::Other => &mut others,
                    PrKind::Skip => continue,
                };
                writeln!(s, "* pr:{}[] {}", pr_num, l.message.as_deref().unwrap_or(&pr_title))
                    .unwrap();
            }
        }
    }

    let contents = format!(
        "\
= Changelog #{}
:sectanchors:
:page-layout: post

Commit: commit:{}[] +
Release: release:{}[]

== Sponsors

**Become a sponsor:** On https://opencollective.com/rust-analyzer/[OpenCollective] or
https://github.com/sponsors/rust-analyzer[GitHub Sponsors].

== New Features

{}

== Fixes

{}

== Internal Improvements

{}

== Others

{}
",
        changelog_n, commit, today, features, fixes, internal, others
    );
    Ok(contents)
}

#[derive(Clone, Copy)]
enum PrKind {
    Feature,
    Fix,
    Internal,
    Other,
    Skip,
}

struct PrInfo {
    message: Option<String>,
    kind: PrKind,
}

fn unescape(s: &str) -> String {
    s.replace(r#"\""#, "").replace(r#"\n"#, "\n").replace(r#"\r"#, "")
}

fn parse_changelog_line(s: &str) -> Option<PrInfo> {
    let parts = s.splitn(3, ' ').collect::<Vec<_>>();
    if parts.len() < 2 || parts[0] != "changelog" {
        return None;
    }
    let message = parts.get(2).map(|it| it.to_string());
    let kind = match parts[1].trim_end_matches(':') {
        "feature" => PrKind::Feature,
        "fix" => PrKind::Fix,
        "internal" => PrKind::Internal,
        "skip" => PrKind::Skip,
        _ => {
            let kind = PrKind::Other;
            let message = format!("{} {}", parts[1], message.unwrap_or_default());
            return Some(PrInfo { kind, message: Some(message) });
        }
    };
    let res = PrInfo { message, kind };
    Some(res)
}

fn parse_title_line(s: &str) -> PrInfo {
    let lower = s.to_ascii_lowercase();
    const PREFIXES: [(&str, PrKind); 5] = [
        ("feat: ", PrKind::Feature),
        ("feature: ", PrKind::Feature),
        ("fix: ", PrKind::Fix),
        ("internal: ", PrKind::Internal),
        ("minor: ", PrKind::Skip),
    ];

    for &(prefix, kind) in &PREFIXES {
        if lower.starts_with(prefix) {
            let message = match &kind {
                PrKind::Skip => None,
                _ => Some(s[prefix.len()..].to_string()),
            };
            return PrInfo { message, kind };
        }
    }
    PrInfo { kind: PrKind::Other, message: Some(s.to_string()) }
}
<commit_msg>Fix changelog generation after repo move<commit_after>use std::fmt::Write;
use std::{env, iter};

use anyhow::bail;
use xshell::{cmd, Shell};

pub(crate) fn get_changelog(
    sh: &Shell,
    changelog_n: usize,
    commit: &str,
    prev_tag: &str,
    today: &str,
) -> anyhow::Result<String> {
    let token = match env::var("GITHUB_TOKEN") {
        Ok(token) => token,
        Err(_) => bail!("Please obtain a personal access token from https://github.com/settings/tokens and set the `GITHUB_TOKEN` environment variable."),
    };

    let git_log = cmd!(sh, "git log {prev_tag}..HEAD --reverse").read()?;
    let mut features = String::new();
    let mut fixes = String::new();
    let mut internal = String::new();
    let mut others = String::new();
    for line in git_log.lines() {
        let line = line.trim_start();
        if let Some(pr_num) = parse_pr_number(&line) {
            let accept = "Accept: application/vnd.github.v3+json";
            let authorization = format!("Authorization: token {}", token);
            let pr_url = "https://api.github.com/repos/rust-lang/rust-analyzer/issues";

            // we don't use an HTTPS client or JSON parser to keep the build times low
            let pr = pr_num.to_string();
            let pr_json =
                cmd!(sh, "curl -s -H {accept} -H {authorization} {pr_url}/{pr}").read()?;
            let pr_title = cmd!(sh, "jq .title").stdin(&pr_json).read()?;
            let pr_title = unescape(&pr_title[1..pr_title.len() - 1]);
            let pr_comment = cmd!(sh, "jq .body").stdin(pr_json).read()?;

            let comments_json =
                cmd!(sh, "curl -s -H {accept} -H {authorization} {pr_url}/{pr}/comments").read()?;
            let pr_comments = cmd!(sh, "jq .[].body").stdin(comments_json).read()?;

            let l = iter::once(pr_comment.as_str())
                .chain(pr_comments.lines())
                .rev()
                .find_map(|it| {
                    let it = unescape(&it[1..it.len() - 1]);
                    it.lines().find_map(parse_changelog_line)
                })
                .into_iter()
                .next()
                .unwrap_or_else(|| parse_title_line(&pr_title));
            let s = match l.kind {
                PrKind::Feature => &mut features,
                PrKind::Fix => &mut fixes,
                PrKind::Internal => &mut internal,
                PrKind::Other => &mut others,
                PrKind::Skip => continue,
            };
            writeln!(s, "* pr:{}[] {}", pr_num, l.message.as_deref().unwrap_or(&pr_title)).unwrap();
        }
    }

    let contents = format!(
        "\
= Changelog #{}
:sectanchors:
:page-layout: post

Commit: commit:{}[] +
Release: release:{}[]

== New Features

{}

== Fixes

{}

== Internal Improvements

{}

== Others

{}
",
        changelog_n, commit, today, features, fixes, internal, others
    );
    Ok(contents)
}

#[derive(Clone, Copy)]
enum PrKind {
    Feature,
    Fix,
    Internal,
    Other,
    Skip,
}

struct PrInfo {
    message: Option<String>,
    kind: PrKind,
}

fn unescape(s: &str) -> String {
    s.replace(r#"\""#, "").replace(r#"\n"#, "\n").replace(r#"\r"#, "")
}

fn parse_pr_number(s: &str) -> Option<u32> {
    const BORS_PREFIX: &str = "Merge #";
    const HOMU_PREFIX: &str = "Auto merge of #";
    if s.starts_with(BORS_PREFIX) {
        let s = &s[BORS_PREFIX.len()..];
        s.parse().ok()
    } else if s.starts_with(HOMU_PREFIX) {
        let s = &s[HOMU_PREFIX.len()..];
        if let Some(space) = s.find(' ') {
            s[..space].parse().ok()
        } else {
            None
        }
    } else {
        None
    }
}

fn parse_changelog_line(s: &str) -> Option<PrInfo> {
    let parts = s.splitn(3, ' ').collect::<Vec<_>>();
    if parts.len() < 2 || parts[0] != "changelog" {
        return None;
    }
    let message = parts.get(2).map(|it| it.to_string());
    let kind = match parts[1].trim_end_matches(':') {
        "feature" => PrKind::Feature,
        "fix" => PrKind::Fix,
        "internal" => PrKind::Internal,
        "skip" => PrKind::Skip,
        _ => {
            let kind = PrKind::Other;
            let message = format!("{} {}", parts[1], message.unwrap_or_default());
            return Some(PrInfo { kind, message: Some(message) });
        }
    };
    let res = PrInfo { message, kind };
    Some(res)
}

fn parse_title_line(s: &str) -> PrInfo {
    let lower = s.to_ascii_lowercase();
    const PREFIXES: [(&str, PrKind); 5] = [
        ("feat: ", PrKind::Feature),
        ("feature: ", PrKind::Feature),
        ("fix: ", PrKind::Fix),
        ("internal: ", PrKind::Internal),
        ("minor: ", PrKind::Skip),
    ];

    for &(prefix, kind) in &PREFIXES {
        if lower.starts_with(prefix) {
            let message = match &kind {
                PrKind::Skip => None,
                _ => Some(s[prefix.len()..].to_string()),
            };
            return PrInfo { message, kind };
        }
    }
    PrInfo { kind: PrKind::Other, message: Some(s.to_string()) }
}
<|endoftext|>


<commit_before>
extern crate ease;

use ease::Client;
use ease::UserAgent;

fn main() {
    println!("{}",
             Client::new("https://api.discogs.com/releases/249504")
                        .ok().expect("Couldn't parse URL.")
                        .header(
                            UserAgent("FooBarApp/2.0".to_owned())
                            )
                        .get()
                        .unwrap()
            );

    println!("\n");

    println!("{}",
             Client::new("http://httpbin.org/post")
                        .ok().expect("Couldn't parse URL.")
                        .param(("foo", "bar"))
                        .post()
                        .unwrap()
            );
}
<commit_msg>Update example.<commit_after>
extern crate ease;

use ease::Client;

fn main() {
    println!("{}",
             Client::new("http://httpbin.org/get")
                        .ok().expect("Couldn't parse URL.")
                        .get()
                        .unwrap()
            );

    println!("\n");

    println!("{}",
             Client::new("http://httpbin.org/post")
                        .ok().expect("Couldn't parse URL.")
                        .param(("foo", "bar"))
                        .post()
                        .unwrap()
            );

    println!("{}",
             Client::new("http://httpbin.org/put")
                        .ok().expect("Couldn't parse URL.")
                        .param(("foo", "bar"))
                        .put()
                        .unwrap()
            );

    println!("{}",
             Client::new("http://httpbin.org/delete")
                        .ok().expect("Couldn't parse URL.")
                        .param(("foo", "bar"))
                        .delete()
                        .unwrap()
            );
}
<|endoftext|>


<commit_before>// This file is released into Public Domain.
#![feature(globs)]
#![feature(struct_variant)]
#![feature(phase)]

#[phase(syntax, link)]
extern crate allegro5;
extern crate allegro_image;
extern crate allegro_font;
extern crate allegro_ttf;
extern crate allegro_audio;
extern crate getopts;

use getopts::*;
use std::os;
use std::c_str::*;
use allegro5::*;
use allegro_image::*;
use allegro_font::*;
use allegro_ttf::*;
use allegro_audio::*;

allegro_main!
{
	let args = os::args();

	let opts = ~[
		optflag("i", "init-only", "only initialize Allegro, don't do anything else")
	];

	let matches = match getopts(args.tail(), opts)
	{
		Ok(m) => { m }
		Err(f) => { fail!(f.to_err_msg()) }
	};

	let init_only = matches.opt_present("i");

	let mut core = Core::init().unwrap();
	println!("Core ok");
	ImageAddon::init(&core).expect("Failed to initialize the image addon");
	println!("Image ok");
	let font_addon = FontAddon::init(&core).expect("Failed to initialize the font addon");
	println!("Font ok");
	let ttf_addon = TtfAddon::init(&font_addon).expect("Failed to initialize the ttf addon");
	println!("Ttf ok");
	let _audio_addon = AudioAddon::init(&core).expect("Failed to initialize the audio addon");
	println!("Audio ok");

	if init_only
	{
		return;
	}

	let disp = core.create_display(800, 600).unwrap();
	disp.set_window_title(&"Rust example".to_c_str());

	core.install_keyboard();
	core.install_mouse();

	let timer = core.create_timer(1.0 / 60.0).unwrap();

	let q = core.create_event_queue().unwrap();
	q.register_event_source(disp.get_event_source());
	q.register_event_source(core.get_keyboard_event_source().unwrap());
	q.register_event_source(core.get_mouse_event_source().unwrap());
	q.register_event_source(timer.get_event_source());

	let bmp = core.create_bitmap(256, 256).unwrap();

	let (mon_x1, mon_y1, mon_x2, mon_y2) = core.get_monitor_info(0).unwrap();
	println!("{} {} {} {}", mon_x1, mon_y1, mon_x2, mon_y2);

	core.set_target_bitmap(&bmp);
	core.clear_to_color(core.map_rgb_f(0.0, 0.0, 1.0));

	let sub_bmp = bmp.create_sub_bitmap(64, 64, 64, 64).unwrap();
	core.set_target_bitmap(&sub_bmp);
	core.clear_to_color(core.map_rgb_f(0.0, 1.0, 1.0));
	core.set_target_bitmap(disp.get_backbuffer());

	let bkg = core.load_bitmap("data/mysha.pcx").unwrap();
	let font = font_addon.create_builtin_font().unwrap();
	let ttf = ttf_addon.load_ttf_font("data/DroidSans.ttf", -32, Flag::zero()).unwrap();
	let white = core.map_rgb_f(1.0, 1.0, 1.0);
	let black = core.map_rgb_f(0.0, 0.0, 0.0);

	let mut theta = 0.0f32;
	let mut redraw = true;
	timer.start();
	'exit: loop
	{
		if redraw && q.is_empty()
		{
			core.clear_to_color(black);
			core.draw_bitmap(&bkg, 0.0, 0.0, Flag::zero());
			core.draw_rotated_bitmap(&bmp, 0.0, 0.0, (disp.get_width() / 2) as f32, (disp.get_height() / 2) as f32, theta, Flag::zero());
			core.draw_text(&font, white, (disp.get_width() / 2) as f32, 32.0, AlignCentre, "Welcome to RustAllegro!");
			core.draw_text(&ttf, white, (disp.get_width() / 2) as f32, 96.0, AlignCentre, "TTF text!");
			disp.flip();
			redraw = false;
		}

		match q.wait_for_event()
		{
			DisplayClose{source: src, ..} =>
			{
				assert!(disp.get_event_source().get_event_source() == src)
				println!("Display close event...")
				break 'exit;
			},
			KeyDown{keycode: k, ..} if k == key::Escape =>
			{
				println!("Pressed Escape!");
				break 'exit;
			},
			KeyChar{unichar: c, ..} =>
			{
				println!("Entered a character: {}", c);
			},
			TimerTick{..} =>
			{
				redraw = true;
				theta = theta + 0.01;
			},
			MouseButtonDown{button: b, ..} =>
			{
				println!("Mouse button {} pressed", b);
			},
			_ => println!("Some other event...")
		}
	}
}
<commit_msg>The deadlock is probably inside Allegro. Disable audio addon initialization on Travis<commit_after>// This file is released into Public Domain.
#![feature(globs)]
#![feature(struct_variant)]
#![feature(phase)]

#[phase(syntax, link)]
extern crate allegro5;
extern crate allegro_image;
extern crate allegro_font;
extern crate allegro_ttf;
extern crate allegro_audio;
extern crate getopts;

use getopts::*;
use std::os;
use std::c_str::*;
use std::os::getenv;
use allegro5::*;
use allegro_image::*;
use allegro_font::*;
use allegro_ttf::*;
use allegro_audio::*;

allegro_main!
{
	let args = os::args();

	let opts = ~[
		optflag("i", "init-only", "only initialize Allegro, don't do anything else")
	];

	let matches = match getopts(args.tail(), opts)
	{
		Ok(m) => { m }
		Err(f) => { fail!(f.to_err_msg()) }
	};

	let init_only = matches.opt_present("i");
	let on_travis = getenv("TRAVIS").is_some();

	let mut core = Core::init().unwrap();
	ImageAddon::init(&core).expect("Failed to initialize the image addon");
	let font_addon = FontAddon::init(&core).expect("Failed to initialize the font addon");
	let ttf_addon = TtfAddon::init(&font_addon).expect("Failed to initialize the ttf addon");

	if init_only && on_travis
	{
		// No Audio on Travis
		return;
	}

	let _audio_addon = AudioAddon::init(&core).expect("Failed to initialize the audio addon");

	if init_only
	{
		return;
	}

	let disp = core.create_display(800, 600).unwrap();
	disp.set_window_title(&"Rust example".to_c_str());

	core.install_keyboard();
	core.install_mouse();

	let timer = core.create_timer(1.0 / 60.0).unwrap();

	let q = core.create_event_queue().unwrap();
	q.register_event_source(disp.get_event_source());
	q.register_event_source(core.get_keyboard_event_source().unwrap());
	q.register_event_source(core.get_mouse_event_source().unwrap());
	q.register_event_source(timer.get_event_source());

	let bmp = core.create_bitmap(256, 256).unwrap();

	let (mon_x1, mon_y1, mon_x2, mon_y2) = core.get_monitor_info(0).unwrap();
	println!("{} {} {} {}", mon_x1, mon_y1, mon_x2, mon_y2);

	core.set_target_bitmap(&bmp);
	core.clear_to_color(core.map_rgb_f(0.0, 0.0, 1.0));

	let sub_bmp = bmp.create_sub_bitmap(64, 64, 64, 64).unwrap();
	core.set_target_bitmap(&sub_bmp);
	core.clear_to_color(core.map_rgb_f(0.0, 1.0, 1.0));
	core.set_target_bitmap(disp.get_backbuffer());

	let bkg = core.load_bitmap("data/mysha.pcx").unwrap();
	let font = font_addon.create_builtin_font().unwrap();
	let ttf = ttf_addon.load_ttf_font("data/DroidSans.ttf", -32, Flag::zero()).unwrap();
	let white = core.map_rgb_f(1.0, 1.0, 1.0);
	let black = core.map_rgb_f(0.0, 0.0, 0.0);

	let mut theta = 0.0f32;
	let mut redraw = true;
	timer.start();
	'exit: loop
	{
		if redraw && q.is_empty()
		{
			core.clear_to_color(black);
			core.draw_bitmap(&bkg, 0.0, 0.0, Flag::zero());
			core.draw_rotated_bitmap(&bmp, 0.0, 0.0, (disp.get_width() / 2) as f32, (disp.get_height() / 2) as f32, theta, Flag::zero());
			core.draw_text(&font, white, (disp.get_width() / 2) as f32, 32.0, AlignCentre, "Welcome to RustAllegro!");
			core.draw_text(&ttf, white, (disp.get_width() / 2) as f32, 96.0, AlignCentre, "TTF text!");
			disp.flip();
			redraw = false;
		}

		match q.wait_for_event()
		{
			DisplayClose{source: src, ..} =>
			{
				assert!(disp.get_event_source().get_event_source() == src)
				println!("Display close event...")
				break 'exit;
			},
			KeyDown{keycode: k, ..} if k == key::Escape =>
			{
				println!("Pressed Escape!");
				break 'exit;
			},
			KeyChar{unichar: c, ..} =>
			{
				println!("Entered a character: {}", c);
			},
			TimerTick{..} =>
			{
				redraw = true;
				theta = theta + 0.01;
			},
			MouseButtonDown{button: b, ..} =>
			{
				println!("Mouse button {} pressed", b);
			},
			_ => println!("Some other event...")
		}
	}
}
<|endoftext|>


<commit_before>//! A simple example which prints out information about available Metal devices

extern crate mtl;

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
fn main() {
    println!("Metal is not supported on this platform");
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
fn main() {
    use mtl::ReadOnlyDevice;
    let device = match mtl::Device::system_default_device() {
        Ok(device) => device,
        Err(e) => {
            use std::error::Error;
            println!("{}", e.description());
            return;
        }
    };

    println!("Device:\t\t\t\t\t\t{}", device.get_name());
    println!("Supports 24 bit stencil and 8 bit depth:\t{}",
             device.is_depth24_stencil8_pixel_format_supported());
    {
        let max_tpg = device.max_threads_per_group();
        println!("Maximum threads per group:\t\t\t({}, {}, {})",
                 max_tpg.width,
                 max_tpg.height,
                 max_tpg.depth);
    }
    println!("Is low power:\t\t\t\t\t{}", device.is_low_power());
    println!("Is headless:\t\t\t\t\t{}", device.is_headless());
}
<commit_msg>Small refactor<commit_after>//! A simple example which prints out information about available Metal devices

extern crate mtl;

use mtl::ReadOnlyDevice;

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
fn main() {
    println!("Metal is not supported on this platform");
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
fn main() {
    let device = match mtl::Device::system_default_device() {
        Ok(device) => device,
        Err(e) => {
            use std::error::Error;
            println!("{}", e.description());
            return;
        }
    };

    println!("Device:\t\t\t\t\t\t{}", device.get_name());
    println!("Supports 24 bit stencil and 8 bit depth:\t{}",
             device.is_depth24_stencil8_pixel_format_supported());
    {
        let max_tpg = device.max_threads_per_group();
        println!("Maximum threads per group:\t\t\t({}, {}, {})",
                 max_tpg.width,
                 max_tpg.height,
                 max_tpg.depth);
    }
    println!("Is low power:\t\t\t\t\t{}", device.is_low_power());
    println!("Is headless:\t\t\t\t\t{}", device.is_headless());
}
<|endoftext|>


<commit_before>//! An example of opening an image.
extern crate image;

use std::env;
use std::fs::File;
use std::path::Path;

use image::GenericImage;

fn main() {
    let file = if env::args().count() == 2 {
        env::args().nth(1).unwrap()
    } else {
        panic!("Please enter a file")
    };

    // Use the open function to load an image from a PAth.
    // ```open``` returns a dynamic image.
    let im = image::open(&Path::new(&file)).unwrap();

    // The dimensions method returns the images width and height
    println!("dimensions {:?}", im.dimensions());

    // The color method returns the image's ColorType
    println!("{:?}", im.color());

    let fout = &mut File::create(&Path::new(&format!("{}.png", file))).unwrap();

    // Write the contents of this image to the Writer in PNG format.
    im.save(fout, image::PNG).unwrap();
}
<commit_msg>fix typo<commit_after>//! An example of opening an image.
extern crate image;

use std::env;
use std::fs::File;
use std::path::Path;

use image::GenericImage;

fn main() {
    let file = if env::args().count() == 2 {
        env::args().nth(1).unwrap()
    } else {
        panic!("Please enter a file")
    };

    // Use the open function to load an image from a Path.
    // ```open``` returns a dynamic image.
    let im = image::open(&Path::new(&file)).unwrap();

    // The dimensions method returns the images width and height
    println!("dimensions {:?}", im.dimensions());

    // The color method returns the image's ColorType
    println!("{:?}", im.color());

    let fout = &mut File::create(&Path::new(&format!("{}.png", file))).unwrap();

    // Write the contents of this image to the Writer in PNG format.
    im.save(fout, image::PNG).unwrap();
}
<|endoftext|>


<commit_before>#![feature(slicing_syntax)]
extern crate irc;

use std::default::Default;
use std::io::timer::sleep;
use std::sync::Arc;
use std::time::duration::Duration;
use irc::data::config::Config;
use irc::server::{IrcServer, Server};
use irc::server::utils::Wrapper;

fn main() {
    let config = Config {
        nickname: Some(format!("pickles")),
        server: Some(format!("irc.fyrechat.net")),
        channels: Some(vec![format!("#vana")]),
        .. Default::default()
    };
    let irc_server = Arc::new(IrcServer::from_config(config).unwrap());
    let irc_server2 = irc_server.clone();
    // The wrapper provides us with methods like send_privmsg(...) and identify(...)
    let server = Wrapper::new(&*irc_server);
    server.identify().unwrap();
    // Let's set up a loop that ignores timeouts, and reads perpetually.
    // n.b. this shouldn't exit automatically if the connection closes.
    spawn(proc() {
        let mut iter = irc_server2.iter();
        loop {
            if let Some(msg) = iter.next() {
                print!("{}", msg.into_string());
            }
        }
    });
    loop {
        server.send_privmsg("#vana", "TWEET TWEET").unwrap();
        sleep(Duration::seconds(10))
    }
}
<commit_msg>Simplified tweeter example code.<commit_after>#![feature(slicing_syntax)]
extern crate irc;

use std::default::Default;
use std::io::timer::sleep;
use std::sync::Arc;
use std::time::duration::Duration;
use irc::data::config::Config;
use irc::server::{IrcServer, Server};
use irc::server::utils::Wrapper;

fn main() {
    let config = Config {
        nickname: Some(format!("pickles")),
        server: Some(format!("irc.fyrechat.net")),
        channels: Some(vec![format!("#vana")]),
        .. Default::default()
    };
    let irc_server = Arc::new(IrcServer::from_config(config).unwrap());
    let irc_server2 = irc_server.clone();
    // The wrapper provides us with methods like send_privmsg(...) and identify(...)
    let server = Wrapper::new(&*irc_server2);
    server.identify().unwrap();
    // Let's set up a loop that just prints the messages.
    spawn(proc() { irc_server.iter().map(|m| print!("{}", m.into_string())).count(); });
    loop {
        server.send_privmsg("#vana", "TWEET TWEET").unwrap();
        sleep(Duration::seconds(10))
    }
}
<|endoftext|>


<commit_before>use screen::*;
use piston_window;
use conrod::{self, Widget, Frameable, Positionable, Sizeable, Labelable};
use conrod::color::Colorable;

pub struct MainMenuScreen {
    ui: conrod::Ui<piston_window::Glyphs>,
    new_game: bool,
    exit: bool,
}

impl MainMenuScreen {
    pub fn new(window: &piston_window::PistonWindow, context: &mut Context) -> MainMenuScreen {
        MainMenuScreen { ui: create_ui(&window, &context.assets_path) }
    }
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self,
                input: &piston_window::Input,
                window: &piston_window::PistonWindow,
                context: &mut Context)
                -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window, context))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        // TODO: Remove?
        const FRAME_WIDTH: f64 = 1.;

        self.ui.set_widgets(|ui| {
            conrod::Canvas::new()
                .frame(FRAME_WIDTH)
                .pad(30.)
                .color(conrod::color::rgb(0.2, 0.35, 0.45))
                .scroll_kids()
                .set(CANVAS, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
//                .top_left_with_margins_on(CANVAS, 0.0, 350.0)
                .rgb(0.4, 0.75, 0.6)
                .frame(FRAME_WIDTH)
                .label("New game")
                .react(|| ())
                .set(NEW_GAME_BUTTON, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(NEW_GAME_BUTTON, 45.0)
                .rgb(0.4, 0.75, 0.6)
                .frame(FRAME_WIDTH)
                .label("Exit")
                .react(|| ())
                .set(EXIT_BUTTON, ui);
        });
    }
}

widget_ids! {
    CANVAS,
    TITLE,
    NEW_GAME_BUTTON,
    EXIT_BUTTON,
}

fn create_ui(window: &piston_window::PistonWindow,
             assets_path: &::std::path::Path)
             -> conrod::Ui<piston_window::Glyphs> {
    let font_path = assets_path.join("NotoSans-Regular.ttf");
    let theme = conrod::Theme::default();
    let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
    conrod::Ui::new(glyph_cache.unwrap(), theme)
}
<commit_msg>MainMenuScreen constructor<commit_after>use screen::*;
use piston_window;
use conrod::{self, Widget, Frameable, Positionable, Sizeable, Labelable};
use conrod::color::Colorable;

pub struct MainMenuScreen {
    ui: conrod::Ui<piston_window::Glyphs>,
    new_game: bool,
    exit: bool,
}

impl MainMenuScreen {
    pub fn new(window: &piston_window::PistonWindow, context: &mut Context) -> MainMenuScreen {
        MainMenuScreen { ui: create_ui(&window, &context.assets_path), new_game: false, exit: false, }
    }
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self,
                input: &piston_window::Input,
                window: &piston_window::PistonWindow,
                context: &mut Context)
                -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window, context))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        // TODO: Remove?
        const FRAME_WIDTH: f64 = 1.;

        self.ui.set_widgets(|ui| {
            conrod::Canvas::new()
                .frame(FRAME_WIDTH)
                .pad(30.)
                .color(conrod::color::rgb(0.2, 0.35, 0.45))
                .scroll_kids()
                .set(CANVAS, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
//                .top_left_with_margins_on(CANVAS, 0.0, 350.0)
                .rgb(0.4, 0.75, 0.6)
                .frame(FRAME_WIDTH)
                .label("New game")
                .react(|| ())
                .set(NEW_GAME_BUTTON, ui);

            conrod::Button::new()
                .w_h(200.0, 50.0)
                .mid_left_of(CANVAS)
                .down_from(NEW_GAME_BUTTON, 45.0)
                .rgb(0.4, 0.75, 0.6)
                .frame(FRAME_WIDTH)
                .label("Exit")
                .react(|| ())
                .set(EXIT_BUTTON, ui);
        });
    }
}

widget_ids! {
    CANVAS,
    TITLE,
    NEW_GAME_BUTTON,
    EXIT_BUTTON,
}

fn create_ui(window: &piston_window::PistonWindow,
             assets_path: &::std::path::Path)
             -> conrod::Ui<piston_window::Glyphs> {
    let font_path = assets_path.join("NotoSans-Regular.ttf");
    let theme = conrod::Theme::default();
    let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
    conrod::Ui::new(glyph_cache.unwrap(), theme)
}
<|endoftext|>


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

trait T1 {}
trait T2 {}

trait Foo {
    type A: T1;
}

trait Bar : Foo {
    type A: T2;
    fn do_something() {
        let _: Self::A; //~ ERROR E0221
    }
}

fn main() {
}
<commit_msg>Updated test for E0221<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

trait T1 {}
trait T2 {}

trait Foo {
    type A: T1;
}

trait Bar : Foo {
    type A: T2;
    fn do_something() {
        let _: Self::A;
        //~^ ERROR E0221
        //~| NOTE ambiguous associated type `A`
        //~| NOTE associated type `Self` could derive from `Foo`
        //~| NOTE associated type `Self` could derive from `Bar`
    }
}

fn main() {
}
<|endoftext|>


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

#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "rustc_platform_intrinsics"]
#![unstable(feature = "rustc_private", issue = "27812")]
#![staged_api]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![feature(staged_api, rustc_private)]

extern crate rustc_llvm as llvm;
extern crate rustc;

use rustc::middle::ty;

pub struct Intrinsic {
    pub inputs: Vec<Type>,
    pub output: Type,

    pub definition: IntrinsicDef,
}

#[derive(Clone, Hash, Eq, PartialEq)]
pub enum Type {
    Integer(/* signed */ bool, u8, /* llvm width */ u8),
    Float(u8),
    Pointer(Box<Type>),
    Vector(Box<Type>, u8),
    Aggregate(bool, Vec<Type>),
}

pub enum IntrinsicDef {
    Named(&'static str),
}

fn i(width: u8) -> Type { Type::Integer(true, width, width) }
fn i_(width: u8, llvm_width: u8) -> Type { Type::Integer(true, width, llvm_width) }
fn u(width: u8) -> Type { Type::Integer(false, width, width) }
#[allow(dead_code)]
fn u_(width: u8, llvm_width: u8) -> Type { Type::Integer(false, width, llvm_width) }
fn f(width: u8) -> Type { Type::Float(width) }
fn v(x: Type, length: u8) -> Type { Type::Vector(Box::new(x), length) }
fn agg(flatten: bool, types: Vec<Type>) -> Type {
    Type::Aggregate(flatten, types)
}

macro_rules! ty {
    (f32x8) => (v(f(32), 8));
    (f64x4) => (v(f(64), 4));

    (i8x32) => (v(i(8), 32));
    (i16x16) => (v(i(16), 16));
    (i32x8) => (v(i(32), 8));
    (i64x4) => (v(i(64), 4));

    (f32x4) => (v(f(32), 4));
    (f64x2) => (v(f(64), 2));

    (i8x16) => (v(i(8), 16));
    (i16x8) => (v(i(16), 8));
    (i32x4) => (v(i(32), 4));
    (i64x2) => (v(i(64), 2));

    (f32x2) => (v(f(32), 2));
    (i8x8) => (v(i(8), 8));
    (i16x4) => (v(i(16), 4));
    (i32x2) => (v(i(32), 2));
    (i64x1)=> (v(i(64), 1));

    (i64) => (i(64));
    (i32) => (i(32));
    (i16) => (i(16));
    (i8) => (i(8));
    (f32) => (f(32));
    (f64) => (f(64));
}
macro_rules! plain {
    ($name: expr, ($($inputs: tt),*) -> $output: tt) => {
        Intrinsic {
            inputs: vec![$(ty!($inputs)),*],
            output: ty!($output),
            definition: ::IntrinsicDef::Named($name)
        }
    }
}

mod x86;
mod arm;
mod aarch64;

impl Intrinsic {
    pub fn find<'tcx>(tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> {
        if name.starts_with("x86_") {
            x86::find(tcx, name)
        } else if name.starts_with("arm_") {
            arm::find(tcx, name)
        } else if name.starts_with("aarch64_") {
            aarch64::find(tcx, name)
        } else {
            None
        }
    }
}
<commit_msg>Delete unused macros from rustc_platform_intrinsics.<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "rustc_platform_intrinsics"]
#![unstable(feature = "rustc_private", issue = "27812")]
#![staged_api]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![feature(staged_api, rustc_private)]

extern crate rustc_llvm as llvm;
extern crate rustc;

use rustc::middle::ty;

pub struct Intrinsic {
    pub inputs: Vec<Type>,
    pub output: Type,

    pub definition: IntrinsicDef,
}

#[derive(Clone, Hash, Eq, PartialEq)]
pub enum Type {
    Integer(/* signed */ bool, u8, /* llvm width */ u8),
    Float(u8),
    Pointer(Box<Type>),
    Vector(Box<Type>, u8),
    Aggregate(bool, Vec<Type>),
}

pub enum IntrinsicDef {
    Named(&'static str),
}

fn i(width: u8) -> Type { Type::Integer(true, width, width) }
fn i_(width: u8, llvm_width: u8) -> Type { Type::Integer(true, width, llvm_width) }
fn u(width: u8) -> Type { Type::Integer(false, width, width) }
#[allow(dead_code)]
fn u_(width: u8, llvm_width: u8) -> Type { Type::Integer(false, width, llvm_width) }
fn f(width: u8) -> Type { Type::Float(width) }
fn v(x: Type, length: u8) -> Type { Type::Vector(Box::new(x), length) }
fn agg(flatten: bool, types: Vec<Type>) -> Type {
    Type::Aggregate(flatten, types)
}

mod x86;
mod arm;
mod aarch64;

impl Intrinsic {
    pub fn find<'tcx>(tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> {
        if name.starts_with("x86_") {
            x86::find(tcx, name)
        } else if name.starts_with("arm_") {
            arm::find(tcx, name)
        } else if name.starts_with("aarch64_") {
            aarch64::find(tcx, name)
        } else {
            None
        }
    }
}
<|endoftext|>