<commit_before>// This file is part of the uutils coreutils package.
//
// (c) Alex Lyon <arcterus@mail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

// spell-checker:ignore (ToDO) Chmoder cmode fmode fperm fref ugoa RFILE RFILE's

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use std::fs;
use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::path::Path;
use uucore::fs::display_permissions_unix;
use uucore::libc::mode_t;
#[cfg(not(windows))]
use uucore::mode;
use uucore::InvalidEncodingHandling;
use walkdir::WalkDir;

static ABOUT: &str = "Change the mode of each FILE to MODE.
 With --reference, change the mode of each FILE to that of RFILE.";

mod options {
    pub const CHANGES: &str = "changes";
    pub const QUIET: &str = "quiet"; // visible_alias("silent")
    pub const VERBOSE: &str = "verbose";
    pub const NO_PRESERVE_ROOT: &str = "no-preserve-root";
    pub const PRESERVE_ROOT: &str = "preserve-root";
    pub const REFERENCE: &str = "RFILE";
    pub const RECURSIVE: &str = "recursive";
    pub const MODE: &str = "MODE";
    pub const FILE: &str = "FILE";
}

fn get_usage() -> String {
    format!(
        "{0} [OPTION]... MODE[,MODE]... FILE...
or: {0} [OPTION]... OCTAL-MODE FILE...
or: {0} [OPTION]... --reference=RFILE FILE...",
        executable!()
    )
}

fn get_long_usage() -> String {
    String::from("Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.")
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let mut args = args
        .collect_str(InvalidEncodingHandling::ConvertLossy)
        .accept_any();

    // Before we can parse 'args' with clap (and previously getopts),
    // a possible MODE prefix '-' needs to be removed (e.g. "chmod -x FILE").
    let mode_had_minus_prefix = strip_minus_from_mode(&mut args);

    let usage = get_usage();
    let after_help = get_long_usage();

    let matches = App::new(executable!())
        .version(crate_version!())
        .about(ABOUT)
        .usage(&usage[..])
        .after_help(&after_help[..])
        .arg(
            Arg::with_name(options::CHANGES)
                .long(options::CHANGES)
                .short("c")
                .help("like verbose but report only when a change is made"),
        )
        .arg(
            Arg::with_name(options::QUIET)
                .long(options::QUIET)
                .visible_alias("silent")
                .short("f")
                .help("suppress most error messages"),
        )
        .arg(
            Arg::with_name(options::VERBOSE)
                .long(options::VERBOSE)
                .short("v")
                .help("output a diagnostic for every file processed"),
        )
        .arg(
            Arg::with_name(options::NO_PRESERVE_ROOT)
                .long(options::NO_PRESERVE_ROOT)
                .help("do not treat '/' specially (the default)"),
        )
        .arg(
            Arg::with_name(options::PRESERVE_ROOT)
                .long(options::PRESERVE_ROOT)
                .help("fail to operate recursively on '/'"),
        )
        .arg(
            Arg::with_name(options::RECURSIVE)
                .long(options::RECURSIVE)
                .short("R")
                .help("change files and directories recursively"),
        )
        .arg(
            Arg::with_name(options::REFERENCE)
                .long("reference")
                .takes_value(true)
                .help("use RFILE's mode instead of MODE values"),
        )
        .arg(
            Arg::with_name(options::MODE)
                .required_unless(options::REFERENCE)
                .takes_value(true),
            // It would be nice if clap could parse with delimiter, e.g. "g-x,u+x",
            // however .multiple(true) cannot be used here because FILE already needs that.
            // Only one positional argument with .multiple(true) set is allowed per command
        )
        .arg(
            Arg::with_name(options::FILE)
                .required_unless(options::MODE)
                .multiple(true),
        )
        .get_matches_from(args);

    let changes = matches.is_present(options::CHANGES);
    let quiet = matches.is_present(options::QUIET);
    let verbose = matches.is_present(options::VERBOSE);
    let preserve_root = matches.is_present(options::PRESERVE_ROOT);
    let recursive = matches.is_present(options::RECURSIVE);
    let fmode = matches
        .value_of(options::REFERENCE)
        .and_then(|fref| match fs::metadata(fref) {
            Ok(meta) => Some(meta.mode()),
            Err(err) => crash!(1, "cannot stat attributes of '{}': {}", fref, err),
        });
    let modes = matches.value_of(options::MODE).unwrap(); // should always be Some because required
    let mut cmode = if mode_had_minus_prefix {
        // clap parsing is finished, now put prefix back
        Some(format!("-{}", modes))
    } else {
        Some(modes.to_string())
    };
    let mut files: Vec<String> = matches
        .values_of(options::FILE)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();
    if fmode.is_some() {
        // "--reference" and MODE are mutually exclusive
        // if "--reference" was used MODE needs to be interpreted as another FILE
        // it wasn't possible to implement this behavior directly with clap
        files.push(cmode.unwrap());
        cmode = None;
    }

    let chmoder = Chmoder {
        changes,
        quiet,
        verbose,
        preserve_root,
        recursive,
        fmode,
        cmode,
    };
    match chmoder.chmod(files) {
        Ok(()) => {}
        Err(e) => return e,
    }

    0
}

// Iterate 'args' and delete the first occurrence
// of a prefix '-' if it's associated with MODE
// e.g. "chmod -v -xw -R FILE" -> "chmod -v xw -R FILE"
pub fn strip_minus_from_mode(args: &mut Vec<String>) -> bool {
    for arg in args {
        if arg.starts_with('-') {
            if let Some(second) = arg.chars().nth(1) {
                match second {
                    'r' | 'w' | 'x' | 'X' | 's' | 't' | 'u' | 'g' | 'o' | '0'..='7' => {
                        // TODO: use strip_prefix() once minimum rust version reaches 1.45.0
                        *arg = arg[1..arg.len()].to_string();
                        return true;
                    }
                    _ => {}
                }
            }
        }
    }
    false
}

struct Chmoder {
    changes: bool,
    quiet: bool,
    verbose: bool,
    preserve_root: bool,
    recursive: bool,
    fmode: Option<u32>,
    cmode: Option<String>,
}

impl Chmoder {
    fn chmod(&self, files: Vec<String>) -> Result<(), i32> {
        let mut r = Ok(());

        for filename in &files {
            let filename = &filename[..];
            let file = Path::new(filename);
            if !file.exists() {
                if is_symlink(file) {
                    println!(
                        "failed to change mode of '{}' from 0000 (---------) to 0000 (---------)",
                        filename
                    );
                    if !self.quiet {
                        show_error!("cannot operate on dangling symlink '{}'", filename);
                    }
                } else {
                    show_error!("cannot access '{}': No such file or directory", filename);
                }
                return Err(1);
            }
            if self.recursive && self.preserve_root && filename == "/" {
                show_error!(
                    "it is dangerous to operate recursively on '{}'\nuse --no-preserve-root to override this failsafe",
                    filename
                );
                return Err(1);
            }
            if !self.recursive {
                r = self.chmod_file(file).and(r);
            } else {
                for entry in WalkDir::new(&filename).into_iter().filter_map(|e| e.ok()) {
                    let file = entry.path();
                    r = self.chmod_file(file).and(r);
                }
            }
        }
        r
    }

    #[cfg(windows)]
    fn chmod_file(&self, file: &Path) -> Result<(), i32> {
        // chmod is useless on Windows
        // it doesn't set any permissions at all
        // instead it just sets the readonly attribute on the file
        Err(0)
    }
    #[cfg(any(unix, target_os = "redox"))]
    fn chmod_file(&self, file: &Path) -> Result<(), i32> {
        let mut fperm = match fs::metadata(file) {
            Ok(meta) => meta.mode() & 0o7777,
            Err(err) => {
                if is_symlink(file) {
                    if self.verbose {
                        println!(
                            "neither symbolic link '{}' nor referent has been changed",
                            file.display()
                        );
                    }
                    return Ok(());
                } else if err.kind() == std::io::ErrorKind::PermissionDenied {
                    show_error!("'{}': Permission denied", file.display());
                } else {
                    show_error!("'{}': {}", file.display(), err);
                }
                return Err(1);
            }
        };
        match self.fmode {
            Some(mode) => self.change_file(fperm, mode, file)?,
            None => {
                let cmode_unwrapped = self.cmode.clone().unwrap();
                for mode in cmode_unwrapped.split(',') {
                    // cmode is guaranteed to be Some in this case
                    let arr: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
                    let result = if mode.contains(arr) {
                        mode::parse_numeric(fperm, mode)
                    } else {
                        mode::parse_symbolic(fperm, mode, file.is_dir())
                    };
                    match result {
                        Ok(mode) => {
                            self.change_file(fperm, mode, file)?;
                            fperm = mode;
                        }
                        Err(f) => {
                            if !self.quiet {
                                show_error!("{}", f);
                            }
                            return Err(1);
                        }
                    }
                }
            }
        }

        Ok(())
    }

    #[cfg(unix)]
    fn change_file(&self, fperm: u32, mode: u32, file: &Path) -> Result<(), i32> {
        if fperm == mode {
            if self.verbose && !self.changes {
                println!(
                    "mode of '{}' retained as {:04o} ({})",
                    file.display(),
                    fperm,
                    display_permissions_unix(fperm as mode_t, false),
                );
            }
            Ok(())
        } else if let Err(err) = fs::set_permissions(file, fs::Permissions::from_mode(mode)) {
            if !self.quiet {
                show_error!("{}", err);
            }
            if self.verbose {
                show_error!(
                    "failed to change mode of file '{}' from {:o} ({}) to {:o} ({})",
                    file.display(),
                    fperm,
                    display_permissions_unix(fperm as mode_t, false),
                    mode,
                    display_permissions_unix(mode as mode_t, false)
                );
            }
            Err(1)
        } else {
            if self.verbose || self.changes {
                show_error!(
                    "mode of '{}' changed from {:o} ({}) to {:o} ({})",
                    file.display(),
                    fperm,
                    display_permissions_unix(fperm as mode_t, false),
                    mode,
                    display_permissions_unix(mode as mode_t, false)
                );
            }
            Ok(())
        }
    }
}

pub fn is_symlink<P: AsRef<Path>>(path: P) -> bool {
    match fs::symlink_metadata(path) {
        Ok(m) => m.file_type().is_symlink(),
        Err(_) => false,
    }
}
<commit_msg>move cmode rather than mut<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Alex Lyon <arcterus@mail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

// spell-checker:ignore (ToDO) Chmoder cmode fmode fperm fref ugoa RFILE RFILE's

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use std::fs;
use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::path::Path;
use uucore::fs::display_permissions_unix;
use uucore::libc::mode_t;
#[cfg(not(windows))]
use uucore::mode;
use uucore::InvalidEncodingHandling;
use walkdir::WalkDir;

static ABOUT: &str = "Change the mode of each FILE to MODE.
 With --reference, change the mode of each FILE to that of RFILE.";

mod options {
    pub const CHANGES: &str = "changes";
    pub const QUIET: &str = "quiet"; // visible_alias("silent")
    pub const VERBOSE: &str = "verbose";
    pub const NO_PRESERVE_ROOT: &str = "no-preserve-root";
    pub const PRESERVE_ROOT: &str = "preserve-root";
    pub const REFERENCE: &str = "RFILE";
    pub const RECURSIVE: &str = "recursive";
    pub const MODE: &str = "MODE";
    pub const FILE: &str = "FILE";
}

fn get_usage() -> String {
    format!(
        "{0} [OPTION]... MODE[,MODE]... FILE...
or: {0} [OPTION]... OCTAL-MODE FILE...
or: {0} [OPTION]... --reference=RFILE FILE...",
        executable!()
    )
}

fn get_long_usage() -> String {
    String::from("Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.")
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let mut args = args
        .collect_str(InvalidEncodingHandling::ConvertLossy)
        .accept_any();

    // Before we can parse 'args' with clap (and previously getopts),
    // a possible MODE prefix '-' needs to be removed (e.g. "chmod -x FILE").
    let mode_had_minus_prefix = strip_minus_from_mode(&mut args);

    let usage = get_usage();
    let after_help = get_long_usage();

    let matches = App::new(executable!())
        .version(crate_version!())
        .about(ABOUT)
        .usage(&usage[..])
        .after_help(&after_help[..])
        .arg(
            Arg::with_name(options::CHANGES)
                .long(options::CHANGES)
                .short("c")
                .help("like verbose but report only when a change is made"),
        )
        .arg(
            Arg::with_name(options::QUIET)
                .long(options::QUIET)
                .visible_alias("silent")
                .short("f")
                .help("suppress most error messages"),
        )
        .arg(
            Arg::with_name(options::VERBOSE)
                .long(options::VERBOSE)
                .short("v")
                .help("output a diagnostic for every file processed"),
        )
        .arg(
            Arg::with_name(options::NO_PRESERVE_ROOT)
                .long(options::NO_PRESERVE_ROOT)
                .help("do not treat '/' specially (the default)"),
        )
        .arg(
            Arg::with_name(options::PRESERVE_ROOT)
                .long(options::PRESERVE_ROOT)
                .help("fail to operate recursively on '/'"),
        )
        .arg(
            Arg::with_name(options::RECURSIVE)
                .long(options::RECURSIVE)
                .short("R")
                .help("change files and directories recursively"),
        )
        .arg(
            Arg::with_name(options::REFERENCE)
                .long("reference")
                .takes_value(true)
                .help("use RFILE's mode instead of MODE values"),
        )
        .arg(
            Arg::with_name(options::MODE)
                .required_unless(options::REFERENCE)
                .takes_value(true),
            // It would be nice if clap could parse with delimiter, e.g. "g-x,u+x",
            // however .multiple(true) cannot be used here because FILE already needs that.
            // Only one positional argument with .multiple(true) set is allowed per command
        )
        .arg(
            Arg::with_name(options::FILE)
                .required_unless(options::MODE)
                .multiple(true),
        )
        .get_matches_from(args);

    let changes = matches.is_present(options::CHANGES);
    let quiet = matches.is_present(options::QUIET);
    let verbose = matches.is_present(options::VERBOSE);
    let preserve_root = matches.is_present(options::PRESERVE_ROOT);
    let recursive = matches.is_present(options::RECURSIVE);
    let fmode = matches
        .value_of(options::REFERENCE)
        .and_then(|fref| match fs::metadata(fref) {
            Ok(meta) => Some(meta.mode()),
            Err(err) => crash!(1, "cannot stat attributes of '{}': {}", fref, err),
        });
    let modes = matches.value_of(options::MODE).unwrap(); // should always be Some because required
    let cmode = if mode_had_minus_prefix {
        // clap parsing is finished, now put prefix back
        format!("-{}", modes)
    } else {
        modes.to_string()
    };
    let mut files: Vec<String> = matches
        .values_of(options::FILE)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();
    let cmode = if fmode.is_some() {
        // "--reference" and MODE are mutually exclusive
        // if "--reference" was used MODE needs to be interpreted as another FILE
        // it wasn't possible to implement this behavior directly with clap
        files.push(cmode);
        None
    } else {
        Some(cmode)
    };

    let chmoder = Chmoder {
        changes,
        quiet,
        verbose,
        preserve_root,
        recursive,
        fmode,
        cmode,
    };
    match chmoder.chmod(files) {
        Ok(()) => {}
        Err(e) => return e,
    }

    0
}

// Iterate 'args' and delete the first occurrence
// of a prefix '-' if it's associated with MODE
// e.g. "chmod -v -xw -R FILE" -> "chmod -v xw -R FILE"
pub fn strip_minus_from_mode(args: &mut Vec<String>) -> bool {
    for arg in args {
        if arg.starts_with('-') {
            if let Some(second) = arg.chars().nth(1) {
                match second {
                    'r' | 'w' | 'x' | 'X' | 's' | 't' | 'u' | 'g' | 'o' | '0'..='7' => {
                        // TODO: use strip_prefix() once minimum rust version reaches 1.45.0
                        *arg = arg[1..arg.len()].to_string();
                        return true;
                    }
                    _ => {}
                }
            }
        }
    }
    false
}

struct Chmoder {
    changes: bool,
    quiet: bool,
    verbose: bool,
    preserve_root: bool,
    recursive: bool,
    fmode: Option<u32>,
    cmode: Option<String>,
}

impl Chmoder {
    fn chmod(&self, files: Vec<String>) -> Result<(), i32> {
        let mut r = Ok(());

        for filename in &files {
            let filename = &filename[..];
            let file = Path::new(filename);
            if !file.exists() {
                if is_symlink(file) {
                    println!(
                        "failed to change mode of '{}' from 0000 (---------) to 0000 (---------)",
                        filename
                    );
                    if !self.quiet {
                        show_error!("cannot operate on dangling symlink '{}'", filename);
                    }
                } else {
                    show_error!("cannot access '{}': No such file or directory", filename);
                }
                return Err(1);
            }
            if self.recursive && self.preserve_root && filename == "/" {
                show_error!(
                    "it is dangerous to operate recursively on '{}'\nuse --no-preserve-root to override this failsafe",
                    filename
                );
                return Err(1);
            }
            if !self.recursive {
                r = self.chmod_file(file).and(r);
            } else {
                for entry in WalkDir::new(&filename).into_iter().filter_map(|e| e.ok()) {
                    let file = entry.path();
                    r = self.chmod_file(file).and(r);
                }
            }
        }
        r
    }

    #[cfg(windows)]
    fn chmod_file(&self, file: &Path) -> Result<(), i32> {
        // chmod is useless on Windows
        // it doesn't set any permissions at all
        // instead it just sets the readonly attribute on the file
        Err(0)
    }
    #[cfg(any(unix, target_os = "redox"))]
    fn chmod_file(&self, file: &Path) -> Result<(), i32> {
        let mut fperm = match fs::metadata(file) {
            Ok(meta) => meta.mode() & 0o7777,
            Err(err) => {
                if is_symlink(file) {
                    if self.verbose {
                        println!(
                            "neither symbolic link '{}' nor referent has been changed",
                            file.display()
                        );
                    }
                    return Ok(());
                } else if err.kind() == std::io::ErrorKind::PermissionDenied {
                    show_error!("'{}': Permission denied", file.display());
                } else {
                    show_error!("'{}': {}", file.display(), err);
                }
                return Err(1);
            }
        };
        match self.fmode {
            Some(mode) => self.change_file(fperm, mode, file)?,
            None => {
                let cmode_unwrapped = self.cmode.clone().unwrap();
                for mode in cmode_unwrapped.split(',') {
                    // cmode is guaranteed to be Some in this case
                    let arr: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
                    let result = if mode.contains(arr) {
                        mode::parse_numeric(fperm, mode)
                    } else {
                        mode::parse_symbolic(fperm, mode, file.is_dir())
                    };
                    match result {
                        Ok(mode) => {
                            self.change_file(fperm, mode, file)?;
                            fperm = mode;
                        }
                        Err(f) => {
                            if !self.quiet {
                                show_error!("{}", f);
                            }
                            return Err(1);
                        }
                    }
                }
            }
        }

        Ok(())
    }

    #[cfg(unix)]
    fn change_file(&self, fperm: u32, mode: u32, file: &Path) -> Result<(), i32> {
        if fperm == mode {
            if self.verbose && !self.changes {
                println!(
                    "mode of '{}' retained as {:04o} ({})",
                    file.display(),
                    fperm,
                    display_permissions_unix(fperm as mode_t, false),
                );
            }
            Ok(())
        } else if let Err(err) = fs::set_permissions(file, fs::Permissions::from_mode(mode)) {
            if !self.quiet {
                show_error!("{}", err);
            }
            if self.verbose {
                show_error!(
                    "failed to change mode of file '{}' from {:o} ({}) to {:o} ({})",
                    file.display(),
                    fperm,
                    display_permissions_unix(fperm as mode_t, false),
                    mode,
                    display_permissions_unix(mode as mode_t, false)
                );
            }
            Err(1)
        } else {
            if self.verbose || self.changes {
                show_error!(
                    "mode of '{}' changed from {:o} ({}) to {:o} ({})",
                    file.display(),
                    fperm,
                    display_permissions_unix(fperm as mode_t, false),
                    mode,
                    display_permissions_unix(mode as mode_t, false)
                );
            }
            Ok(())
        }
    }
}

pub fn is_symlink<P: AsRef<Path>>(path: P) -> bool {
    match fs::symlink_metadata(path) {
        Ok(m) => m.file_type().is_symlink(),
        Err(_) => false,
    }
}
<|endoftext|>


<commit_before>#![allow(warnings)]

mod hlt;
use hlt::{ networking, types };
use std::collections::HashMap;

struct MoveFeatures {
    loc: types::Location,
    d: u8,
    owner_them: u8,
    distance: i32,
    friendly: bool,
    strength_us: i32,
    strength_them: i32,
    adjacent_strength_us: i32,
    assigned_strength: i32,
    production_them: i32,
    production_us: i32,
}

fn get_total_adjacent_strength(loc: types::Location, map: &types::GameMap, my_id: u8) -> i32 {
    // Check to see if we can use multiple moves to capture
    let total_adjacent_strength: i32 = types::CARDINALS.iter()
        .map(|d| {
            let site = map.get_site_ref(loc, *d);
            if site.owner == my_id { site.strength as i32 } else { 0 }
        })
        .sum();
    total_adjacent_strength
}

fn get_best_move_simple(
    loc: types::Location,
    map: &types::GameMap,
    my_id: u8,
    current_moves: &HashMap<types::Location, i32>) -> Vec<(types::Location, u8)>  {
    let mut moves = vec![];
    for d in &types::CARDINALS {
        let proposed_loc = map.get_location(loc, *d);
        let proposed = map.get_site_ref(loc, *d);
        let current = map.get_site_ref(loc, types::STILL);
        let already_assigned_strength: i32 = *current_moves.get(&proposed_loc)
            .unwrap_or(&0i32);
        moves.push(MoveFeatures {
            loc: loc,
            d: *d,
            distance: distance_to_border(loc, *d, &map, my_id),
            owner_them: proposed.owner,
            friendly: proposed.owner == my_id,
            strength_us: current.strength as i32,
            strength_them: proposed.strength as i32,
            adjacent_strength_us: get_total_adjacent_strength(proposed_loc, &map, my_id),
            assigned_strength: already_assigned_strength,
            production_us: current.production as i32,
            production_them: proposed.production as i32,
        });
    }
    // Sort by distance
    moves.sort_by(|a, b| a.distance.cmp(&b.distance));
    // Remove all but the shortest distances and filter losing battles and strength losses
    let shortest = moves[0].distance;
    let mut moves: Vec<MoveFeatures> = moves.into_iter()
        // Don't move weak pieces
        .filter(|a| a.strength_us > a.production_us * 5)
        // Only move towards the closest border
        .filter(|a| a.distance == shortest)
        // Don't allow losing battles
        .filter(|a| a.adjacent_strength_us > (a.strength_them + a.production_them))
        // Allow a small loss so full strength don't get stuck
        .filter(|a| !a.friendly || a.strength_us + a.strength_them <= 260)
        // Don't allow too many troops to move into the same space
        .filter(|a| a.strength_us + a.assigned_strength <= 260)
        .collect();
    match moves.len() {
        0 => return vec![(loc, types::STILL)],
        _ => {},
    };
    // If there's still more than one move available, go for production
    moves.sort_by(|a, b| a.production_them.cmp(&b.production_them));
    // Prefer losing less strength
    moves.sort_by(|a, b| b.strength_them.cmp(&a.strength_them));

    let m = moves.pop().unwrap();
    if m.strength_us > m.strength_them {
        vec![(m.loc, m.d)]
    } else {
        // We need to issue additional orders for other troups
        let mut r = vec![(m.loc, m.d)];
        let proposed = map.get_location(m.loc, m.d);
        for adj in &types::CARDINALS {
            let adj_loc = map.get_location(proposed, *adj);
            r.push((adj_loc, reverse(adj)));
        }
        r
    }
}

fn distance_to_border(loc: types::Location, dir: u8, map: &types::GameMap, my_id: u8) -> i32 {
    let mut l = loc.clone();
    let mut counter = 0;
    loop {
        if map.get_site_ref(l, types::STILL).owner != my_id {
            return counter
        }
        l = map.get_location(l, dir);
        if l == loc {
            return map.width as i32
        }
        counter += 1;
    }
}

fn get_units_of_player(id: u8, map: &types::GameMap) -> Vec<types::Location> {
    let mut result = Vec::new();
    for a in 0..map.height {
        for b in 0..map.width {
            let l = types::Location { x: b, y: a };
            let site = map.get_site_ref(l, types::STILL);
            if site.owner == id {
                result.push(l);
            }
        }
    }
    result
}

fn local_best_strategy(my_id: u8, game_map: &types::GameMap) -> HashMap<types::Location, u8> {
    let mut moves = HashMap::new();
    let mut planned_moves: HashMap<types::Location, i32> = HashMap::new();
    for l in get_units_of_player(my_id, game_map) {
        if moves.contains_key(&l) {
            continue;
        }

        let next = get_best_move_simple(l, game_map, my_id, &planned_moves);
        for (loc, d) in next {
            let site = game_map.get_site_ref(loc, types::STILL);
            let next_loc = game_map.get_location(loc, d);

            // Record the planned move
            let strength = site.strength as i32;
            *planned_moves.entry(loc).or_insert(strength) -= strength;
            *planned_moves.entry(next_loc).or_insert(0) += strength;

            moves.insert(loc, d);
        }
    }
    moves
}

fn max_capture_strategy(my_id: u8, game_map: &types::GameMap) -> HashMap<types::Location, u8> {
    let my_units = get_units_of_player(my_id, &game_map);
    let mut possibilities = my_units
        .iter()
        .flat_map(|l| {
            types::CARDINALS.iter()
                .cloned()
                .map(move |d| (*l, d))
                .collect::<Vec<_>>()
        })
        .map(|(l, d)| {
            let proposed = game_map.get_site_ref(l, d);
            let current = game_map.get_site_ref(l, types::STILL);
            MoveFeatures {
                loc: l,
                d: d,
                distance: 1,
                owner_them: proposed.owner,
                friendly: proposed.owner == my_id,
                strength_us: current.strength as i32,
                strength_them: proposed.strength as i32,
                adjacent_strength_us: get_total_adjacent_strength(l, &game_map, my_id),
                assigned_strength: 0,
                production_us: current.production as i32,
                production_them: proposed.production as i32,
            }
        })
        // Don't move weak pieces
        .filter(|a| a.strength_us > a.production_us * 3)
        // Only consider moves that move us toward victory!
        .filter(|a| !a.friendly)
        .filter(|a| a.adjacent_strength_us + a.strength_us > a.strength_them)
        .collect::<Vec<_>>();
    possibilities.sort_by(|a, b| b.strength_them.cmp(&a.strength_them));
    possibilities.sort_by(|a, b| a.strength_us.cmp(&b.strength_us));
    possibilities.sort_by(|a, b| a.production_them.cmp(&b.production_them));

    let mut moves = HashMap::new();
    while possibilities.len() > 0 {
        let m = possibilities.pop().unwrap();
        if moves.contains_key(&m.loc) {
            continue
        }
        if m.strength_us > m.strength_them {
            // If we can capture, do so
            moves.insert(m.loc, m.d);
        } else {
            // Otherwise, move everything towards that point
            for adj in &types::CARDINALS {
                let adj_loc = game_map.get_location(m.loc, *adj);
                if !moves.contains_key(&adj_loc) {
                    moves.insert(adj_loc, reverse(adj));
                }
            }
            moves.insert(m.loc, types::STILL);
        }
    }
    for remaining in my_units {
        if !moves.contains_key(&remaining) {
            moves.insert(remaining, types::STILL);
        }
    }
    moves
}

fn reverse(d: &u8) -> u8 {
    match d {
        &types::NORTH => types::SOUTH,
        &types::SOUTH => types::NORTH,
        &types::WEST => types::EAST,
        &types::EAST => types::WEST,
        _ => panic!("unknown direction {}", d),
    }
}

fn find_poi(map: &types::GameMap, my_id: u8) -> Vec<types::Location> {
    let mut result = Vec::new();
    for a in 0..map.height {
        for b in 0..map.width {
            let l = types::Location { x: b, y: a };
            let site = map.get_site_ref(l, types::STILL);
            if site.production >= 5 && site.owner != my_id {
                result.push(l);
            }
        }
    }
    result
}

fn find_closest_poi(l: types::Location, map: &types::GameMap, poi: &Vec<types::Location>) -> types::Location {
    poi.iter()
    .min_by_key(|p| map.get_distance(l, **p)).unwrap_or(&types::Location{x: 0, y: 0}).clone()
}

fn poi_strategy(my_id: u8, game_map: &types::GameMap) -> HashMap<types::Location, u8> {
    let poi = find_poi(game_map, my_id);
    let my_units = get_units_of_player(my_id, &game_map);
    let unit_count = my_units.len();
    let mut moves = HashMap::new();
    let mut targets: HashMap<types::Location, ()> = HashMap::new();
    for l in my_units {
        let site = game_map.get_site_ref(l, types::STILL);
        if site.strength < site.production * 5 {
            moves.insert(l, types::STILL);
        } else {
            let closest = find_closest_poi(l, game_map, &poi);
            let d = game_map.get_direction(l, closest);
            let proposed_loc = game_map.get_location(l, d);
            if site.strength > game_map.get_site_ref(proposed_loc, types::STILL).strength {
                moves.insert(l, d);
            }
            targets.insert(closest, ());
        }
    }
    //log(
    //    format!("{} POI, {} units, {} distinct targets\n", poi.len(), unit_count, targets.len()),
    //    my_id
    //);
    moves
}

use std::io::prelude::*;
use std::fs::OpenOptions;
fn log(s: String, id: u8) {
    let mut file = OpenOptions::new()
         .append(true)
         .create(true)
         .open(format!("output-{}.log", id))
         .unwrap();
    file.write(s.as_bytes()).unwrap();
}

fn main() {
    let (my_id, mut game_map) = networking::get_init();
    networking::send_init(format!("{}{}", "Asp2Insp".to_string(), my_id.to_string()));
    let mut turn_counter = 0;
    loop {
        networking::get_frame(&mut game_map);
        //let moves = poi_strategy(my_id, &game_map);

        let my_count = get_units_of_player(my_id, &game_map).len();
        let moves = if my_count < 20 {
            max_capture_strategy(my_id, &game_map)
        } else {
            local_best_strategy(my_id, &game_map)
        };
        networking::send_frame(moves);
        turn_counter += 1;
    }
}
<commit_msg>Starting on special cases classifier<commit_after>#![allow(warnings)]

mod hlt;
use hlt::networking;
use hlt::types::*;
use std::collections::{HashMap, HashSet};

struct MoveFeatures {
    loc: Location,
    d: u8,
    owner_them: u8,
    distance: i32,
    friendly: bool,
    strength_us: i32,
    strength_them: i32,
    adjacent_strength_us: i32,
    assigned_strength: i32,
    production_them: i32,
    production_us: i32,
}

fn get_total_adjacent_strength(loc: Location, map: &GameMap, my_id: u8) -> i32 {
    // Check to see if we can use multiple moves to capture
    let total_adjacent_strength: i32 = CARDINALS.iter()
        .map(|d| {
            let site = map.get_site_ref(loc, *d);
            if site.owner == my_id { site.strength as i32 } else { 0 }
        })
        .sum();
    total_adjacent_strength
}

fn get_best_move_simple(
    loc: Location,
    map: &GameMap,
    my_id: u8,
    current_moves: &HashMap<Location, i32>) -> Vec<(Location, u8)>  {
    let mut moves = vec![];
    for d in &CARDINALS {
        let proposed_loc = map.get_location(loc, *d);
        let proposed = map.get_site_ref(loc, *d);
        let current = map.get_site_ref(loc, STILL);
        let already_assigned_strength: i32 = *current_moves.get(&proposed_loc)
            .unwrap_or(&0i32);
        moves.push(MoveFeatures {
            loc: loc,
            d: *d,
            distance: distance_to_border(loc, *d, &map, my_id),
            owner_them: proposed.owner,
            friendly: proposed.owner == my_id,
            strength_us: current.strength as i32,
            strength_them: proposed.strength as i32,
            adjacent_strength_us: get_total_adjacent_strength(proposed_loc, &map, my_id),
            assigned_strength: already_assigned_strength,
            production_us: current.production as i32,
            production_them: proposed.production as i32,
        });
    }
    // Sort by distance
    moves.sort_by(|a, b| a.distance.cmp(&b.distance));
    // Remove all but the shortest distances and filter losing battles and strength losses
    let shortest = moves[0].distance;
    let mut moves: Vec<MoveFeatures> = moves.into_iter()
        // Don't move weak pieces
        .filter(|a| a.strength_us > a.production_us * 5)
        // Only move towards the closest border
        .filter(|a| a.distance == shortest)
        // Don't allow losing battles
        .filter(|a| a.adjacent_strength_us > (a.strength_them + a.production_them))
        // Allow a small loss so full strength don't get stuck
        .filter(|a| !a.friendly || a.strength_us + a.strength_them <= 260)
        // Don't allow too many troops to move into the same space
        .filter(|a| a.strength_us + a.assigned_strength <= 260)
        .collect();
    match moves.len() {
        0 => return vec![(loc, STILL)],
        _ => {},
    };
    // If there's still more than one move available, go for production
    moves.sort_by(|a, b| a.production_them.cmp(&b.production_them));
    // Prefer losing less strength
    moves.sort_by(|a, b| b.strength_them.cmp(&a.strength_them));

    let m = moves.pop().unwrap();
    if m.strength_us > m.strength_them {
        vec![(m.loc, m.d)]
    } else {
        // We need to issue additional orders for other troups
        let mut r = vec![(m.loc, m.d)];
        let proposed = map.get_location(m.loc, m.d);
        for adj in &CARDINALS {
            let adj_loc = map.get_location(proposed, *adj);
            r.push((adj_loc, reverse(adj)));
        }
        r
    }
}

fn distance_to_border(loc: Location, dir: u8, map: &GameMap, my_id: u8) -> i32 {
    let mut l = loc.clone();
    let mut counter = 0;
    loop {
        if map.get_site_ref(l, STILL).owner != my_id {
            return counter
        }
        l = map.get_location(l, dir);
        if l == loc {
            return map.width as i32
        }
        counter += 1;
    }
}

fn get_units_of_player(id: u8, map: &GameMap) -> Vec<Location> {
    let mut result = Vec::new();
    for a in 0..map.height {
        for b in 0..map.width {
            let l = Location { x: b, y: a };
            let site = map.get_site_ref(l, STILL);
            if site.owner == id {
                result.push(l);
            }
        }
    }
    result
}

fn local_best_strategy(my_id: u8, game_map: &GameMap) -> HashMap<Location, u8> {
    let mut moves = HashMap::new();
    let mut planned_moves: HashMap<Location, i32> = HashMap::new();
    for l in get_units_of_player(my_id, game_map) {
        if moves.contains_key(&l) {
            continue;
        }

        let next = get_best_move_simple(l, game_map, my_id, &planned_moves);
        for (loc, d) in next {
            let site = game_map.get_site_ref(loc, STILL);
            let next_loc = game_map.get_location(loc, d);

            // Record the planned move
            let strength = site.strength as i32;
            *planned_moves.entry(loc).or_insert(strength) -= strength;
            *planned_moves.entry(next_loc).or_insert(0) += strength;

            moves.insert(loc, d);
        }
    }
    moves
}

fn max_capture_strategy(my_id: u8, game_map: &GameMap) -> HashMap<Location, u8> {
    let my_units = get_units_of_player(my_id, &game_map);
    let mut possibilities = my_units
        .iter()
        .flat_map(|l| {
            CARDINALS.iter()
                .cloned()
                .map(move |d| (*l, d))
                .collect::<Vec<_>>()
        })
        .map(|(l, d)| {
            let proposed = game_map.get_site_ref(l, d);
            let current = game_map.get_site_ref(l, STILL);
            MoveFeatures {
                loc: l,
                d: d,
                distance: 1,
                owner_them: proposed.owner,
                friendly: proposed.owner == my_id,
                strength_us: current.strength as i32,
                strength_them: proposed.strength as i32,
                adjacent_strength_us: get_total_adjacent_strength(l, &game_map, my_id),
                assigned_strength: 0,
                production_us: current.production as i32,
                production_them: proposed.production as i32,
            }
        })
        // Don't move weak pieces
        .filter(|a| a.strength_us > a.production_us * 3)
        // Only consider moves that move us toward victory!
        .filter(|a| !a.friendly)
        .filter(|a| a.adjacent_strength_us + a.strength_us > a.strength_them)
        .collect::<Vec<_>>();
    possibilities.sort_by(|a, b| b.strength_them.cmp(&a.strength_them));
    possibilities.sort_by(|a, b| a.strength_us.cmp(&b.strength_us));
    possibilities.sort_by(|a, b| a.production_them.cmp(&b.production_them));

    let mut moves = HashMap::new();
    while possibilities.len() > 0 {
        let m = possibilities.pop().unwrap();
        if moves.contains_key(&m.loc) {
            continue
        }
        if m.strength_us > m.strength_them {
            // If we can capture, do so
            moves.insert(m.loc, m.d);
        } else {
            // Otherwise, move everything towards that point
            for adj in &CARDINALS {
                let adj_loc = game_map.get_location(m.loc, *adj);
                if !moves.contains_key(&adj_loc) {
                    moves.insert(adj_loc, reverse(adj));
                }
            }
            moves.insert(m.loc, STILL);
        }
    }
    for remaining in my_units {
        if !moves.contains_key(&remaining) {
            moves.insert(remaining, STILL);
        }
    }
    moves
}

fn reverse(d: &u8) -> u8 {
    match d {
        &NORTH => SOUTH,
        &SOUTH => NORTH,
        &WEST => EAST,
        &EAST => WEST,
        _ => panic!("unknown direction {}", d),
    }
}

fn find_poi(map: &GameMap, my_id: u8) -> Vec<Location> {
    let mut result = Vec::new();
    for a in 0..map.height {
        for b in 0..map.width {
            let l = Location { x: b, y: a };
            let site = map.get_site_ref(l, STILL);
            if site.production >= 5 && site.owner != my_id {
                result.push(l);
            }
        }
    }
    result
}

fn find_closest_poi(l: Location, map: &GameMap, poi: &Vec<Location>) -> Location {
    poi.iter()
    .min_by_key(|p| map.get_distance(l, **p)).unwrap_or(&Location{x: 0, y: 0}).clone()
}

fn poi_strategy(my_id: u8, game_map: &GameMap) -> HashMap<Location, u8> {
    let poi = find_poi(game_map, my_id);
    let my_units = get_units_of_player(my_id, &game_map);
    let unit_count = my_units.len();
    let mut moves = HashMap::new();
    let mut targets: HashMap<Location, ()> = HashMap::new();
    for l in my_units {
        let site = game_map.get_site_ref(l, STILL);
        if site.strength < site.production * 5 {
            moves.insert(l, STILL);
        } else {
            let closest = find_closest_poi(l, game_map, &poi);
            let d = game_map.get_direction(l, closest);
            let proposed_loc = game_map.get_location(l, d);
            if site.strength > game_map.get_site_ref(proposed_loc, STILL).strength {
                moves.insert(l, d);
            }
            targets.insert(closest, ());
        }
    }
    //log(
    //    format!("{} POI, {} units, {} distinct targets\n", poi.len(), unit_count, targets.len()),
    //    my_id
    //);
    moves
}

use std::io::prelude::*;
use std::fs::OpenOptions;
fn log(s: String, id: u8) {
    let mut file = OpenOptions::new()
         .append(true)
         .create(true)
         .open(format!("output-{}.log", id))
         .unwrap();
    file.write(s.as_bytes()).unwrap();
}

#[derive(Copy, Clone)]
enum Troop {
    Weak(Location), // Gotta sit on production longer
    Interior(Location), // Surrounded by at least 1 square of friendly
    VerticalWall(Location), // A straight line along the enemy
    HorizontalWall(Location), // A straight line along the enemy
    Pincer(Location, Location), // Two troops that can corner against an enemy
    Pincer3(Location, Location, Location), // Three troops that are almost surrounding an enemy
    Lance(Location), // Surrounded on three sides by enemy
    Island(Location), // Surrounded on all 8 sides by enemy
    Reinforcement(Location), // Surrounded by friendly, but with a diagonal enemy
    Unknown(Location),
}

fn classify(locs: Vec<Location>, map: &GameMap, my_id: u8) -> Vec<Troop> {
    let mut done: HashSet<Location> = HashSet::new();
    let mut result = Vec::new();
    for l in locs {
        if done.contains(&l) {
            continue
        }
        let t = classify_loc(l, map, my_id);
        use Troop::*;
        match t {
            Pincer(l1, l2) => {
                done.insert(l1); done.insert(l2);
            },
            Pincer3(l1, l2, l3) => {
                done.insert(l1); done.insert(l2); done.insert(l3);
            },
            _ => {
                done.insert(l);
            },
        };
        result.push(t);
    }
    result
}

fn classify_loc(loc: Location, map: &GameMap, my_id: u8) -> Troop {
    use Troop::*;
    let owner = |l| { map.get_site_ref(l, STILL).owner };
    let strength = |l| { map.get_site_ref(l, STILL).strength };
    let production = |l| { map.get_site_ref(l, STILL).production };
    let get_location = |l, d1, d2| {
        map.get_location(map.get_location(l, d1), d2)
    };
    let friendly = |l| { if map.get_site_ref(l, STILL).owner == my_id {1} else {0} };

    if strength(loc) < production(loc) {
        return Weak(loc)
    }
    // nw nn ne
    // ww    ee
    // sw ss se
    let (nw, nn, ne) = (get_location(loc, WEST, NORTH), map.get_location(loc, NORTH), get_location(loc, EAST, NORTH));
    let (ww, ee) = (map.get_location(loc, WEST), map.get_location(loc, EAST));
    let (sw, ss, se) = (get_location(loc, WEST, SOUTH), map.get_location(loc, SOUTH), get_location(loc, EAST, SOUTH));

    let surroundings = (friendly(nw), friendly(nn), friendly(ne),
                       friendly(ww),               friendly(ee),
                       friendly(sw), friendly(ss), friendly(se));
    match surroundings {
        (1, 1, 1,
         1,    1,
         1, 1, 1) => Interior(loc),
        (_, 1, _,
         1,    1,
         _, 1, _) => Reinforcement(loc),
        (_, 0, _,
         0,    0,
         _, 0, _) => Island(loc),
        (_, a, _,
         d,    b,
         _, c, _) if a + b + c + d == 1 => Lance(loc),
        (_, 1, _,
         a,    b,
         _, 1, _) if a + b < 2 => VerticalWall(loc),
        (_, a, _,
         1,    1,
         _, b, _) if a + b < 2 => HorizontalWall(loc),
        (1, 0, 1,
         _,    _,
         _, _, _) => Pincer3(nw, loc, ne),
        (1, _, _,
         0,    _,
         1, _, _) => Pincer3(nw, loc, sw),
        (_, _, 1,
         _,    0,
         _, _, 1) => Pincer3(ne, loc, se),
        (_, _, _,
         _,    _,
         1, 0, 1) => Pincer3(sw, loc, se),

        (1, 0, _,
         _,    _,
         _, _, _) => Pincer(nw, loc),
        (_, _, _,
         0,    _,
         1, _, _) => Pincer(loc, sw),
        (_, _, 1,
         _,    0,
         _, _, _) => Pincer(ne, loc),
        (_, _, _,
         _,    _,
         1, 0, _) => Pincer(sw, loc),
        (_, 0, 1,
         _,    _,
         _, _, _) => Pincer(loc, ne),
        (1, _, _,
         0,    _,
         _, _, _) => Pincer(nw, loc),
        (_, _, _,
         _,    0,
         _, _, 1) => Pincer(loc, se),
        (_, _, _,
         _,    _,
         _, 0, 1) => Pincer(loc, se),
        _ => Unknown(loc),
    }
}

fn main() {
    let (my_id, mut game_map) = networking::get_init();
    networking::send_init(format!("{}{}", "Asp2Insp".to_string(), my_id.to_string()));
    let mut turn_counter = 0;
    loop {
        networking::get_frame(&mut game_map);
        //let moves = poi_strategy(my_id, &game_map);

        let my_count = get_units_of_player(my_id, &game_map).len();
        let moves = if my_count < 20 {
            max_capture_strategy(my_id, &game_map)
        } else {
            local_best_strategy(my_id, &game_map)
        };
        networking::send_frame(moves);
        turn_counter += 1;
    }
}
<|endoftext|>


<commit_before>use std::io::BufReader;
    use std::io::BufRead;
    use std::fs::File;

    fn main() {
        let f = File::open("data/SRR062634.filt.fastq").unwrap();
        let file = BufReader::new(&f);
        for (num, line) in file.lines().enumerate() {
            let l = line.unwrap();
            if  num % 4 == 0 {
            let chars: String = l.chars().skip(1).collect();
            println!(">{}", chars);
            }
            if  num % 4 == 1  {
                println!("{}", l);
             }
        }
    }
<commit_msg>removed dummy file<commit_after><|endoftext|>


<commit_before>/**
 * https://github.com/mozilla/rust/wiki/Doc-unit-testing
 * rustc unittest.rs --test -o unittest
 * ./unittest --test
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */
#[cfg(test)]
mod tests {
	#[test]
	fn testFail() {
		assert!(1 == 2, "This test must fail!");
	}
	#[test]
	fn testSuccess() {
		assert!(1 == 1);
	}
}
fn main() {
	println("This program must be build and run with --test");
}
<commit_msg>unittest.rs : Comment testFail()<commit_after>/**
 * https://github.com/mozilla/rust/wiki/Doc-unit-testing
 * rustc unittest.rs --test -o unittest
 * ./unittest --test
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */
#[cfg(test)]
mod tests {
	/* This test is commented to avoid false negative tests.
	#[test]
	fn testFail() {
		assert!(1 == 2, "This test must fail!");
	}
	*/
	#[test]
	fn testSuccess() {
		assert!(1 == 1);
	}
}
fn main() {
	println("This program must be build and run with --test");
}
<|endoftext|>


<commit_before>use std::env;
use std::ffi::CString;
use std::path::PathBuf;
use std::process::{Command, exit, Stdio};
use std::time::Instant;

use crate::argument::Argument;
use crate::core::*;

const TMUX: &str = "tmux";

pub struct Tmux<'a> {
    nmk_dir: &'a PathBuf,
    tmux_dir: PathBuf,
    bin: String,
    version: String,
}

impl<'a> Tmux<'a> {
    pub fn new(nmk_dir: &PathBuf, tmux_dir: PathBuf) -> Tmux {
        Tmux {
            nmk_dir,
            tmux_dir,
            bin: which::which(TMUX).unwrap().to_str().unwrap().to_string(),
            version: Tmux::call_check_version(),
        }
    }

    pub fn version(&self) -> &str {
        &self.version
    }

    fn conf(&self) -> PathBuf {
        let conf_file = format!("{}.conf", &self.version);
        let conf_path = self.tmux_dir.join(conf_file);
        if !conf_path.exists() {
            error!("tmux {} is not supported", &self.version)
        }
        conf_path
    }

    pub fn setup(&self, arg: &Argument) {
        set_env("NMK_TMUX_DEFAULT_SHELL", which::which("zsh").expect("zsh not found"));
        set_env("NMK_TMUX_DETACH_ON_DESTROY", on_off!(arg.detach_on_destroy));
        set_env("NMK_TMUX_HISTORY", self.nmk_dir.join("tmux").join(".tmux_history"));
        set_env("NMK_TMUX_VERSION", &self.version);
    }

    fn print_usage_time(&self, arg: &Argument, start: &Instant) {
        let before_exec = start.elapsed().as_millis();
        if arg.usage {
            println!("{}", before_exec);
        } else {
            debug!("usage time: {}ms", before_exec);
        }
    }

    fn call_check_version() -> String {
        if let Ok(o) = Command::new(TMUX).arg("-V").output() {
            if !o.status.success() {
                match o.status.code() {
                    Some(i) => error!("tmux exit with status: {}", i),
                    None => error!("terminated by signal"),
                };
                exit(1);
            }
            let version_output = String::from_utf8(o.stdout)
                .expect("tmux version output contain non utf-8");
            version_output.trim().split(" ")
                .nth(1).expect(&format!("bad output: {}", version_output))
                .to_string()
        } else {
            error!("{} not found", TMUX);
            exit(1);
        }
    }

    pub fn login_shell(&self, arg: Argument, start: Instant) -> ! {
        let mut vec = Vec::new();

        vec.push(TMUX);
        vec.push("-L");
        vec.push(arg.socket());
        if arg.force256color {
            vec.push("-2");
        }
        vec.push("-f");
        let config = self.conf();
        vec.push(config.to_str().unwrap());
        vec.push("-c");
        vec.push("exec zsh --login");
        let exec_args: Vec<_> = vec.into_iter().flat_map(CString::new).collect();
        let exec_name = CString::new(self.bin.as_bytes()).unwrap();
        debug!("{:#?}", exec_name);
        debug!("{:#?}", exec_args);
        self.print_usage_time(&arg, &start);
        if nix::unistd::execv(&exec_name, &exec_args).is_err() {
            error!("Can't start login shell")
        }
        // this code is never reach if exec success
        exit(1);
    }

    pub fn exec(&self, arg: Argument, start: Instant) -> ! {
        let mut vec = Vec::new();
        let config = self.conf();
        vec.push(TMUX);
        vec.push("-L");
        let socket = arg.socket();
        vec.push(socket);
        if arg.force256color {
            vec.push("-2");
        }
        let tmux_args = arg.tmux_args();
        if is_running(socket) {
            if tmux_args.len() > 0 {
                vec.extend(tmux_args);
            } else {
                if env::var_os("TMUX").is_some() && !arg.inception {
                    warn!("add --inception to allow nested tmux sessions");
                    exit(1);
                }
                vec.push("attach");
            }
        } else {
            vec.push("-f");
            vec.push(config.to_str().unwrap());
            vec.extend(tmux_args);
        }
        let exec_args: Vec<_> = vec.into_iter().flat_map(CString::new).collect();
        let exec_name = CString::new(self.bin.as_bytes()).unwrap();
        debug!("{:#?}", exec_name);
        debug!("{:#?}", exec_args);
        self.print_usage_time(&arg, &start);
        if nix::unistd::execv(&exec_name, &exec_args).is_err() {
            error!("Can't start tmux")
        }
        // this code is never reach if exec success
        exit(1);
    }
}

pub fn is_running(socket: &str) -> bool {
    let running = Command::new(TMUX)
        .arg("-L")
        .arg(socket)
        .arg("list-sessions")
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
        .map(|o| o.success())
        .unwrap_or_default();
    debug!("server {} running", if running { "is" } else { "is not" });
    running
}

pub fn dir(nmk_dir: &PathBuf) -> PathBuf {
    let path = nmk_dir.join("tmux");
    if !path.exists() {
        panic!("{:?} doesn't exist", path);
    }
    path
}
<commit_msg>nmk.rs: explicitly inform tmux that terminal support unicode<commit_after>use std::env;
use std::ffi::CString;
use std::path::PathBuf;
use std::process::{Command, exit, Stdio};
use std::time::Instant;

use crate::argument::Argument;
use crate::core::*;

const TMUX: &str = "tmux";

pub struct Tmux<'a> {
    nmk_dir: &'a PathBuf,
    tmux_dir: PathBuf,
    bin: String,
    version: String,
}

impl<'a> Tmux<'a> {
    pub fn new(nmk_dir: &PathBuf, tmux_dir: PathBuf) -> Tmux {
        Tmux {
            nmk_dir,
            tmux_dir,
            bin: which::which(TMUX).unwrap().to_str().unwrap().to_string(),
            version: Tmux::call_check_version(),
        }
    }

    pub fn version(&self) -> &str {
        &self.version
    }

    fn conf(&self) -> PathBuf {
        let conf_file = format!("{}.conf", &self.version);
        let conf_path = self.tmux_dir.join(conf_file);
        if !conf_path.exists() {
            error!("tmux {} is not supported", &self.version)
        }
        conf_path
    }

    pub fn setup(&self, arg: &Argument) {
        set_env("NMK_TMUX_DEFAULT_SHELL", which::which("zsh").expect("zsh not found"));
        set_env("NMK_TMUX_DETACH_ON_DESTROY", on_off!(arg.detach_on_destroy));
        set_env("NMK_TMUX_HISTORY", self.nmk_dir.join("tmux").join(".tmux_history"));
        set_env("NMK_TMUX_VERSION", &self.version);
    }

    fn print_usage_time(&self, arg: &Argument, start: &Instant) {
        let before_exec = start.elapsed().as_millis();
        if arg.usage {
            println!("{}", before_exec);
        } else {
            debug!("usage time: {}ms", before_exec);
        }
    }

    fn call_check_version() -> String {
        if let Ok(o) = Command::new(TMUX).arg("-V").output() {
            if !o.status.success() {
                match o.status.code() {
                    Some(i) => error!("tmux exit with status: {}", i),
                    None => error!("terminated by signal"),
                };
                exit(1);
            }
            let version_output = String::from_utf8(o.stdout)
                .expect("tmux version output contain non utf-8");
            version_output.trim().split(" ")
                .nth(1).expect(&format!("bad output: {}", version_output))
                .to_string()
        } else {
            error!("{} not found", TMUX);
            exit(1);
        }
    }

    pub fn login_shell(&self, arg: Argument, start: Instant) -> ! {
        let mut vec = Vec::new();

        vec.push(TMUX);
        vec.push("-L");
        vec.push(arg.socket());
        if arg.force256color {
            vec.push("-2");
        }
        vec.push("-f");
        let config = self.conf();
        vec.push(config.to_str().unwrap());
        vec.push("-c");
        vec.push("exec zsh --login");
        let exec_args: Vec<_> = vec.into_iter().flat_map(CString::new).collect();
        let exec_name = CString::new(self.bin.as_bytes()).unwrap();
        debug!("{:#?}", exec_name);
        debug!("{:#?}", exec_args);
        self.print_usage_time(&arg, &start);
        if nix::unistd::execv(&exec_name, &exec_args).is_err() {
            error!("Can't start login shell")
        }
        // this code is never reach if exec success
        exit(1);
    }

    pub fn exec(&self, arg: Argument, start: Instant) -> ! {
        let mut vec = Vec::new();
        let config = self.conf();
        vec.push(TMUX);
        vec.push("-L");
        let socket = arg.socket();
        vec.push(socket);
        if arg.force256color {
            vec.push("-2");
        }
        if arg.unicode || arg.force8color {
            vec.push("-u");
        }
        let tmux_args = arg.tmux_args();
        if is_running(socket) {
            if tmux_args.len() > 0 {
                vec.extend(tmux_args);
            } else {
                if env::var_os("TMUX").is_some() && !arg.inception {
                    warn!("add --inception to allow nested tmux sessions");
                    exit(1);
                }
                vec.push("attach");
            }
        } else {
            vec.push("-f");
            vec.push(config.to_str().unwrap());
            vec.extend(tmux_args);
        }
        let exec_args: Vec<_> = vec.into_iter().flat_map(CString::new).collect();
        let exec_name = CString::new(self.bin.as_bytes()).unwrap();
        debug!("{:#?}", exec_name);
        debug!("{:#?}", exec_args);
        self.print_usage_time(&arg, &start);
        if nix::unistd::execv(&exec_name, &exec_args).is_err() {
            error!("Can't start tmux")
        }
        // this code is never reach if exec success
        exit(1);
    }
}

pub fn is_running(socket: &str) -> bool {
    let running = Command::new(TMUX)
        .arg("-L")
        .arg(socket)
        .arg("list-sessions")
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
        .map(|o| o.success())
        .unwrap_or_default();
    debug!("server {} running", if running { "is" } else { "is not" });
    running
}

pub fn dir(nmk_dir: &PathBuf) -> PathBuf {
    let path = nmk_dir.join("tmux");
    if !path.exists() {
        panic!("{:?} doesn't exist", path);
    }
    path
}
<|endoftext|>


<commit_before><commit_msg>Tidy BlockGraph, use parking_lot, add doc comments<commit_after><|endoftext|>


<commit_before><commit_msg>Fix Formatting<commit_after><|endoftext|>


<commit_before>//! Compares the decoding results with reference renderings.

extern crate crc32fast;
extern crate glob;
extern crate image;

use std::fs;
use std::io;
use std::path::PathBuf;
use std::u32;

use crc32fast::Hasher as Crc32;

const BASE_PATH: [&str; 2] = [".", "tests"];
const IMAGE_DIR: &str = "images";
const OUTPUT_DIR: &str = "output";
const REFERENCE_DIR: &str = "reference";

fn process_images<F>(dir: &str, input_decoder: Option<&str>, func: F)
where
    F: Fn(&PathBuf, PathBuf, &str),
{
    let base: PathBuf = BASE_PATH.iter().collect();
    let decoders = &["tga", "tiff", "png", "gif", "bmp", "ico", "jpg", "hdr", "pbm", "webp"];
    for decoder in decoders {
        let mut path = base.clone();
        path.push(dir);
        path.push(decoder);
        path.push("**");
        path.push(
            "*.".to_string() + match input_decoder {
                Some(val) => val,
                None => decoder,
            },
        );
        let pattern = &*format!("{}", path.display());
        for path in glob::glob(pattern).unwrap().filter_map(Result::ok) {
            func(&base, path, decoder)
        }
    }
}

#[cfg(feature = "png")]
#[test]
fn render_images() {
    process_images(IMAGE_DIR, None, |base, path, decoder| {
        println!("render_images {}", path.display());
        let img = match image::open(&path) {
            Ok(img) => img.to_rgba(),
            // Do not fail on unsupported error
            // This might happen because the testsuite contains unsupported images
            // or because a specific decoder included via a feature.
            Err(image::ImageError::UnsupportedError(e)) => {
                println!("UNSUPPORTED {}: {}", path.display(), e);
                return;
            }
            Err(err) => panic!(format!("decoding of {:?} failed with: {}", path, err)),
        };
        let mut crc = Crc32::new();
        crc.update(&*img);

        let (filename, testsuite) = {
            let mut path: Vec<_> = path.components().collect();
            (path.pop().unwrap(), path.pop().unwrap())
        };
        let mut out_path = base.clone();

        out_path.push(OUTPUT_DIR);
        out_path.push(decoder);
        out_path.push(testsuite.as_os_str());
        fs::create_dir_all(&out_path).unwrap();
        out_path.push(format!(
            "{}.{}.{}",
            filename.as_os_str().to_str().unwrap(),
            format!("{:x}", crc.finalize()),
            "png"
        ));
        img.save(out_path).unwrap();
    })
}

#[test]
fn check_references() {
    process_images(REFERENCE_DIR, Some("png"), |base, path, decoder| {
        println!("check_references {}", path.display());

        let ref_img = match image::open(&path) {
            Ok(img) => img.to_rgba(),
            // Do not fail on unsupported error
            // This might happen because the testsuite contains unsupported images
            // or because a specific decoder included via a feature.
            Err(image::ImageError::UnsupportedError(_)) => return,
            Err(err) => panic!(format!("{}", err)),
        };

        let (filename, testsuite) = {
            let mut path: Vec<_> = path.components().collect();
            (path.pop().unwrap(), path.pop().unwrap())
        };

        let mut filename_parts = filename
            .as_os_str()
            .to_str()
            .unwrap()
            .split('.')
            .collect::<Vec<_>>();

        // Ignore the file extension
        filename_parts.pop().unwrap();

        // The penultimate part of `filename_parts` represents the metadata.
        let meta_str = filename_parts.pop().unwrap();
        let mut meta = meta_str.split('_').collect::<Vec<_>>();
        let ref_crc;
        let anim_frame: Option<usize>;

        if meta.len() == 1 {
            // `CRC`
            ref_crc = meta.pop().unwrap();
            anim_frame = None;
        } else if meta.len() == 3 && meta[0] == "anim" {
            // `anim_FRAME_CRC`
            ref_crc = meta.pop().unwrap();
            let frame: usize = meta.pop().unwrap().parse().unwrap();
            anim_frame = Some(frame.checked_sub(1).expect("frame number cannot be 0"));
        } else {
            panic!(
                "unrecognized reference image metadata format: {:?}",
                meta_str
            );
        }

        // The remaining part represents the original file name
        let orig_filename = filename_parts.join(".");

        // Check the reference image's CRC
        let ref_crc = u32::from_str_radix(ref_crc, 16).unwrap();

        let ref_crc_actual = {
            let mut hasher = Crc32::new();
            hasher.update(&*ref_img);
            hasher.finalize()
        };

        if ref_crc_actual != ref_crc {
            panic!(
                "Reference rendering hash check failed (expected = {:08x}, actual = {:08x}).",
                ref_crc, ref_crc_actual
            );
        }

        let mut img_path = base.clone();
        img_path.push(IMAGE_DIR);
        img_path.push(decoder);
        img_path.push(testsuite.as_os_str());
        img_path.push(orig_filename);

        // Load the test image
        let test_img;

        if let Some(anim_frame) = anim_frame {
            #[cfg(feature = "gif_codec")]
            {
                // Interpret the input file as an animation file and extract a
                // single frame
                use image::AnimationDecoder;
                let stream = io::BufReader::new(fs::File::open(&img_path).unwrap());
                let decoder = match image::gif::Decoder::new(stream) {
                    Ok(decoder) => decoder,
                    Err(image::ImageError::UnsupportedError(_)) => return,
                    Err(err) => panic!(format!("decoding of {:?} failed with: {}", img_path, err)),
                };

                let mut frames = match decoder.into_frames().collect_frames() {
                    Ok(frames) => frames,
                    Err(image::ImageError::UnsupportedError(_)) => return,
                    Err(err) => panic!(format!(
                        "collecting frames of {:?} failed with: {}",
                        img_path, err
                    )),
                };

                let frame = frames.drain(anim_frame..).nth(0).unwrap();

                // Convert the frame to a`RgbaImage`
                test_img = frame.into_buffer();
            }

            #[cfg(not(feature = "gif_codec"))]
            {
                println!("Skipping - GIF codec is not enabled");
                return;
            }
        } else {
            // Read the input file as a single image
            match image::open(&img_path) {
                Ok(img) => test_img = img.to_rgba(),
                // Do not fail on unsupported error
                // This might happen because the testsuite contains unsupported images
                // or because a specific decoder included via a feature.
                Err(image::ImageError::UnsupportedError(_)) => return,
                Err(err) => panic!(format!("decoding of {:?} failed with: {}", img_path, err)),
            };
        }

        if *ref_img != *test_img {
            panic!("Reference rendering does not match.");
        }
    })
}

#[cfg(feature = "hdr")]
#[test]
fn check_hdr_references() {
    let mut ref_path: PathBuf = BASE_PATH.iter().collect();
    ref_path.push(REFERENCE_DIR);
    ref_path.push("hdr");
    let mut path: PathBuf = BASE_PATH.iter().collect();
    path.push(IMAGE_DIR);
    path.push("hdr");
    path.push("*");
    path.push("*.hdr");
    let pattern = &*format!("{}", path.display());
    for path in glob::glob(pattern).unwrap().filter_map(Result::ok) {
        use std::path::Component::Normal;
        let mut ref_path = ref_path.clone();
        // append 2 last components of image path to reference path
        for c in path.components()
            .rev()
            .take(2)
            .collect::<Vec<_>>()
            .iter()
            .rev()
        {
            match *c {
                Normal(name) => ref_path.push(name),
                _ => panic!(),
            }
        }
        ref_path.set_extension("raw");
        println!("{}", ref_path.display());
        println!("{}", path.display());
        let decoder = image::hdr::HDRDecoder::new(io::BufReader::new(
            fs::File::open(&path).unwrap(),
        )).unwrap();
        let decoded = decoder.read_image_hdr().unwrap();
        let reference = image::hdr::read_raw_file(&ref_path).unwrap();
        assert_eq!(decoded, reference);
    }
}

/// Check that BMP files with large values could cause OOM issues are rejected.
///
/// The images are postfixed with `bad_bmp` to not be loaded by the other test.
#[test]
fn bad_bmps() {
    let path: PathBuf = BASE_PATH
        .iter()
        .collect::<PathBuf>()
        .join(IMAGE_DIR)
        .join("bmp/images")
        .join("*.bad_bmp");

    let pattern = &*format!("{}", path.display());
    for path in glob::glob(pattern).unwrap().filter_map(Result::ok) {
        let im = image::open(path);
        assert!(im.is_err());
    }
}
<commit_msg>Refactor `check_references`<commit_after>//! Compares the decoding results with reference renderings.

extern crate crc32fast;
extern crate glob;
extern crate image;

use std::fs;
use std::io;
use std::path::PathBuf;
use std::u32;

use crc32fast::Hasher as Crc32;

const BASE_PATH: [&str; 2] = [".", "tests"];
const IMAGE_DIR: &str = "images";
const OUTPUT_DIR: &str = "output";
const REFERENCE_DIR: &str = "reference";

fn process_images<F>(dir: &str, input_decoder: Option<&str>, func: F)
where
    F: Fn(&PathBuf, PathBuf, &str),
{
    let base: PathBuf = BASE_PATH.iter().collect();
    let decoders = &["tga", "tiff", "png", "gif", "bmp", "ico", "jpg", "hdr", "pbm", "webp"];
    for decoder in decoders {
        let mut path = base.clone();
        path.push(dir);
        path.push(decoder);
        path.push("**");
        path.push(
            "*.".to_string() + match input_decoder {
                Some(val) => val,
                None => decoder,
            },
        );
        let pattern = &*format!("{}", path.display());
        for path in glob::glob(pattern).unwrap().filter_map(Result::ok) {
            func(&base, path, decoder)
        }
    }
}

#[cfg(feature = "png")]
#[test]
fn render_images() {
    process_images(IMAGE_DIR, None, |base, path, decoder| {
        println!("render_images {}", path.display());
        let img = match image::open(&path) {
            Ok(img) => img.to_rgba(),
            // Do not fail on unsupported error
            // This might happen because the testsuite contains unsupported images
            // or because a specific decoder included via a feature.
            Err(image::ImageError::UnsupportedError(e)) => {
                println!("UNSUPPORTED {}: {}", path.display(), e);
                return;
            }
            Err(err) => panic!(format!("decoding of {:?} failed with: {}", path, err)),
        };
        let mut crc = Crc32::new();
        crc.update(&*img);

        let (filename, testsuite) = {
            let mut path: Vec<_> = path.components().collect();
            (path.pop().unwrap(), path.pop().unwrap())
        };
        let mut out_path = base.clone();

        out_path.push(OUTPUT_DIR);
        out_path.push(decoder);
        out_path.push(testsuite.as_os_str());
        fs::create_dir_all(&out_path).unwrap();
        out_path.push(format!(
            "{}.{}.{}",
            filename.as_os_str().to_str().unwrap(),
            format!("{:x}", crc.finalize()),
            "png"
        ));
        img.save(out_path).unwrap();
    })
}

/// Describes a single test case of `check_references`.
struct ReferenceTestCase {
    orig_filename: String,
    crc: u32,
    ty: ReferenceTestCaseType,
}

enum ReferenceTestCaseType {
    /// The test image is loaded using `image::open`, and the result is compared
    /// against the reference image.
    SingleImage,

    /// From the test image file, a single frame is extracted using
    /// `image::gif::Decoder`, and the result is compared against the reference
    /// image.
    AnimatedGifFrame {
        /// A zero-based frame number.
        frame: usize,
    },
}

impl std::str::FromStr for ReferenceTestCase {
    type Err = &'static str;

    /// Construct `ReferenceTestCase` from the file name of a reference
    /// image.
    fn from_str(filename: &str) -> Result<Self, Self::Err> {
        let mut filename_parts = filename.rsplitn(3, '.');

        // Ignore the file extension
        filename_parts.next().unwrap();

        // The penultimate part of `filename_parts` represents the metadata,
        // describing the test type and other details.
        let meta_str = filename_parts.next().ok_or("missing metadata part")?;
        let meta = meta_str.split('_').collect::<Vec<_>>();
        let (crc, ty);

        if meta.len() == 1 {
            // `CRC`
            crc = parse_crc(&meta[0]).ok_or("malformed CRC")?;
            ty = ReferenceTestCaseType::SingleImage;
        } else if meta.len() == 3 && meta[0] == "anim" {
            // `anim_FRAME_CRC`
            crc = parse_crc(&meta[2]).ok_or("malformed CRC")?;
            let frame: usize = meta[1].parse().map_err(|_| "malformed frame number")?;
            ty = ReferenceTestCaseType::AnimatedGifFrame {
                frame: frame.checked_sub(1).ok_or("frame number must be 1-based")?,
            };
        } else {
            return Err("unrecognized reference image metadata format");
        }

        // The remaining part represents the original file name
        let orig_filename = filename_parts
            .next()
            .ok_or("missing original file name")?
            .to_owned();

        Ok(Self {
            orig_filename,
            crc,
            ty,
        })
    }
}

/// Parse the given string as a hexadecimal CRC hash, used by `check_references`.
fn parse_crc(src: &str) -> Option<u32> {
    u32::from_str_radix(src, 16).ok()
}

#[test]
fn check_references() {
    process_images(REFERENCE_DIR, Some("png"), |base, path, decoder| {
        println!("check_references {}", path.display());

        let ref_img = match image::open(&path) {
            Ok(img) => img.to_rgba(),
            // Do not fail on unsupported error
            // This might happen because the testsuite contains unsupported images
            // or because a specific decoder included via a feature.
            Err(image::ImageError::UnsupportedError(_)) => return,
            Err(err) => panic!(format!("{}", err)),
        };

        let (filename, testsuite) = {
            let mut path: Vec<_> = path.components().collect();
            (path.pop().unwrap(), path.pop().unwrap())
        };

        // Parse the file name to obtain the test case information
        let filename_str = filename.as_os_str().to_str().unwrap();
        let case: ReferenceTestCase = filename_str.parse().unwrap();

        // Check the reference image's CRC
        let ref_crc = case.crc;

        let ref_crc_actual = {
            let mut hasher = Crc32::new();
            hasher.update(&*ref_img);
            hasher.finalize()
        };

        if ref_crc_actual != ref_crc {
            panic!(
                "Reference rendering hash check failed (expected = {:08x}, actual = {:08x}).",
                ref_crc, ref_crc_actual
            );
        }

        let mut img_path = base.clone();
        img_path.push(IMAGE_DIR);
        img_path.push(decoder);
        img_path.push(testsuite.as_os_str());
        img_path.push(case.orig_filename);

        // Load the test image
        let test_img;

        match case.ty {
            ReferenceTestCaseType::AnimatedGifFrame { frame: frame_num } => {
                #[cfg(feature = "gif_codec")]
                {
                    // Interpret the input file as an animation file
                    use image::AnimationDecoder;
                    let stream = io::BufReader::new(fs::File::open(&img_path).unwrap());
                    let decoder = match image::gif::Decoder::new(stream) {
                        Ok(decoder) => decoder,
                        Err(image::ImageError::UnsupportedError(_)) => return,
                        Err(err) => {
                            panic!(format!("decoding of {:?} failed with: {}", img_path, err))
                        }
                    };

                    let mut frames = match decoder.into_frames().collect_frames() {
                        Ok(frames) => frames,
                        Err(image::ImageError::UnsupportedError(_)) => return,
                        Err(err) => panic!(format!(
                            "collecting frames of {:?} failed with: {}",
                            img_path, err
                        )),
                    };

                    // Select a single frame
                    let frame = frames.drain(frame_num..).nth(0).unwrap();

                    // Convert the frame to a`RgbaImage`
                    test_img = frame.into_buffer();
                }

                #[cfg(not(feature = "gif_codec"))]
                {
                    println!("Skipping - GIF codec is not enabled");
                    return;
                }
            }

            ReferenceTestCaseType::SingleImage => {
                // Read the input file as a single image
                match image::open(&img_path) {
                    Ok(img) => test_img = img.to_rgba(),
                    // Do not fail on unsupported error
                    // This might happen because the testsuite contains unsupported images
                    // or because a specific decoder included via a feature.
                    Err(image::ImageError::UnsupportedError(_)) => return,
                    Err(err) => panic!(format!("decoding of {:?} failed with: {}", img_path, err)),
                };
            }
        }

        if *ref_img != *test_img {
            panic!("Reference rendering does not match.");
        }
    })
}

#[cfg(feature = "hdr")]
#[test]
fn check_hdr_references() {
    let mut ref_path: PathBuf = BASE_PATH.iter().collect();
    ref_path.push(REFERENCE_DIR);
    ref_path.push("hdr");
    let mut path: PathBuf = BASE_PATH.iter().collect();
    path.push(IMAGE_DIR);
    path.push("hdr");
    path.push("*");
    path.push("*.hdr");
    let pattern = &*format!("{}", path.display());
    for path in glob::glob(pattern).unwrap().filter_map(Result::ok) {
        use std::path::Component::Normal;
        let mut ref_path = ref_path.clone();
        // append 2 last components of image path to reference path
        for c in path.components()
            .rev()
            .take(2)
            .collect::<Vec<_>>()
            .iter()
            .rev()
        {
            match *c {
                Normal(name) => ref_path.push(name),
                _ => panic!(),
            }
        }
        ref_path.set_extension("raw");
        println!("{}", ref_path.display());
        println!("{}", path.display());
        let decoder = image::hdr::HDRDecoder::new(io::BufReader::new(
            fs::File::open(&path).unwrap(),
        )).unwrap();
        let decoded = decoder.read_image_hdr().unwrap();
        let reference = image::hdr::read_raw_file(&ref_path).unwrap();
        assert_eq!(decoded, reference);
    }
}

/// Check that BMP files with large values could cause OOM issues are rejected.
///
/// The images are postfixed with `bad_bmp` to not be loaded by the other test.
#[test]
fn bad_bmps() {
    let path: PathBuf = BASE_PATH
        .iter()
        .collect::<PathBuf>()
        .join(IMAGE_DIR)
        .join("bmp/images")
        .join("*.bad_bmp");

    let pattern = &*format!("{}", path.display());
    for path in glob::glob(pattern).unwrap().filter_map(Result::ok) {
        let im = image::open(path);
        assert!(im.is_err());
    }
}
<|endoftext|>


<commit_before>extern crate actix_web;
extern crate http;
extern crate time;

use actix_web::*;
use http::{header, Method, Uri, Version, HeaderMap, HttpTryFrom};

#[test]
fn test_no_request_cookies() {
    let mut req = HttpRequest::new(
        Method::GET, Uri::try_from("/").unwrap(), Version::HTTP_11, HeaderMap::new());
    assert!(req.cookies().is_empty());
    let _ = req.load_cookies();
    assert!(req.cookies().is_empty());
}

#[test]
fn test_request_cookies() {
    let mut headers = HeaderMap::new();
    headers.insert(header::COOKIE,
                   header::HeaderValue::from_static("cookie1=value1; cookie2=value2"));

    let mut req = HttpRequest::new(
        Method::GET, Uri::try_from("/").unwrap(), Version::HTTP_11, headers);
    assert!(req.cookies().is_empty());
    {
        let cookies = req.load_cookies().unwrap();
        assert_eq!(cookies.len(), 2);
        assert_eq!(cookies[0].name(), "cookie1");
        assert_eq!(cookies[0].value(), "value1");
        assert_eq!(cookies[1].name(), "cookie2");
        assert_eq!(cookies[1].value(), "value2");
    }

    let cookie = req.cookie("cookie1");
    assert!(cookie.is_some());
    let cookie = cookie.unwrap();
    assert_eq!(cookie.name(), "cookie1");
    assert_eq!(cookie.value(), "value1");

    let cookie = req.cookie("cookie-unknown");
    assert!(cookie.is_none());
}

#[test]
fn test_no_request_range_header() {
    let req = HttpRequest::new(Method::GET, Uri::try_from("/").unwrap(),
                               Version::HTTP_11, HeaderMap::new());
    let ranges = req.range(100).unwrap();
    assert!(ranges.is_empty());
}

#[test]
fn test_request_range_header() {
    let mut headers = HeaderMap::new();
    headers.insert(header::RANGE,
                   header::HeaderValue::from_static("bytes=0-4"));

    let req = HttpRequest::new(Method::GET, Uri::try_from("/").unwrap(),
                               Version::HTTP_11, headers);
    let ranges = req.range(100).unwrap();
    assert_eq!(ranges.len(), 1);
    assert_eq!(ranges[0].start, 0);
    assert_eq!(ranges[0].length, 5);
}

#[test]
fn test_request_query() {
    let req = HttpRequest::new(Method::GET, Uri::try_from("/?id=test").unwrap(),
                               Version::HTTP_11, HeaderMap::new());

    assert_eq!(req.query_string(), "id=test");
    let query: Vec<_> = req.query().collect();
    assert_eq!(query[0].0.as_ref(), "id");
    assert_eq!(query[0].1.as_ref(), "test");
}
<commit_msg>test woth with_params<commit_after>extern crate actix_web;
extern crate http;
extern crate time;

use actix_web::*;
use http::{header, Method, Uri, Version, HeaderMap, HttpTryFrom};

#[test]
fn test_no_request_cookies() {
    let mut req = HttpRequest::new(
        Method::GET, Uri::try_from("/").unwrap(), Version::HTTP_11, HeaderMap::new());
    assert!(req.cookies().is_empty());
    let _ = req.load_cookies();
    assert!(req.cookies().is_empty());
}

#[test]
fn test_request_cookies() {
    let mut headers = HeaderMap::new();
    headers.insert(header::COOKIE,
                   header::HeaderValue::from_static("cookie1=value1; cookie2=value2"));

    let mut req = HttpRequest::new(
        Method::GET, Uri::try_from("/").unwrap(), Version::HTTP_11, headers);
    assert!(req.cookies().is_empty());
    {
        let cookies = req.load_cookies().unwrap();
        assert_eq!(cookies.len(), 2);
        assert_eq!(cookies[0].name(), "cookie1");
        assert_eq!(cookies[0].value(), "value1");
        assert_eq!(cookies[1].name(), "cookie2");
        assert_eq!(cookies[1].value(), "value2");
    }

    let cookie = req.cookie("cookie1");
    assert!(cookie.is_some());
    let cookie = cookie.unwrap();
    assert_eq!(cookie.name(), "cookie1");
    assert_eq!(cookie.value(), "value1");

    let cookie = req.cookie("cookie-unknown");
    assert!(cookie.is_none());
}

#[test]
fn test_no_request_range_header() {
    let req = HttpRequest::new(Method::GET, Uri::try_from("/").unwrap(),
                               Version::HTTP_11, HeaderMap::new());
    let ranges = req.range(100).unwrap();
    assert!(ranges.is_empty());
}

#[test]
fn test_request_range_header() {
    let mut headers = HeaderMap::new();
    headers.insert(header::RANGE,
                   header::HeaderValue::from_static("bytes=0-4"));

    let req = HttpRequest::new(Method::GET, Uri::try_from("/").unwrap(),
                               Version::HTTP_11, headers);
    let ranges = req.range(100).unwrap();
    assert_eq!(ranges.len(), 1);
    assert_eq!(ranges[0].start, 0);
    assert_eq!(ranges[0].length, 5);
}

#[test]
fn test_request_query() {
    let req = HttpRequest::new(Method::GET, Uri::try_from("/?id=test").unwrap(),
                               Version::HTTP_11, HeaderMap::new());

    assert_eq!(req.query_string(), "id=test");
    let query: Vec<_> = req.query().collect();
    assert_eq!(query[0].0.as_ref(), "id");
    assert_eq!(query[0].1.as_ref(), "test");
}

#[test]
fn test_request_params() {
    let req = HttpRequest::new(Method::GET, Uri::try_from("/?id=test").unwrap(),
                               Version::HTTP_11, HeaderMap::new());

    let mut params = Params::new();
    params.insert("key".to_owned(), "value".to_owned());

    let req = req.with_params(params);
    assert_eq!(req.params().find("key"), Some("value"));
}
<|endoftext|>


<commit_before>use crate::prelude::*;
use neon::prelude::*;
use stencila::serve;

/// Serve a path
pub fn serve(mut cx: FunctionContext) -> JsResult<JsString> {
    let path = &cx.argument::<JsString>(0)?.value(&mut cx);

    let result = RUNTIME.block_on(async { serve::serve(path, None, false).await });
    to_string_or_throw(cx, result)
}
<commit_msg>fix(Node bindings): Correct module name<commit_after>use crate::prelude::*;
use neon::prelude::*;
use stencila::server;

/// Serve a path
pub fn serve(mut cx: FunctionContext) -> JsResult<JsString> {
    let path = &cx.argument::<JsString>(0)?.value(&mut cx);

    let result = RUNTIME.block_on(async { server::serve(path, None, false).await });
    to_string_or_throw(cx, result)
}
<|endoftext|>


<commit_before>
import util::interner;
import lexer::reader;

type str_num = uint;

enum binop {
    PLUS,
    MINUS,
    STAR,
    SLASH,
    PERCENT,
    CARET,
    AND,
    OR,
    LSL,
    LSR,
    ASR,
}

enum token {
    /* Expression-operator symbols. */
    EQ,
    LT,
    LE,
    EQEQ,
    NE,
    GE,
    GT,
    ANDAND,
    OROR,
    NOT,
    TILDE,
    BINOP(binop),
    BINOPEQ(binop),

    /* Structural symbols */
    AT,
    DOT,
    ELLIPSIS,
    COMMA,
    SEMI,
    COLON,
    MOD_SEP,
    RARROW,
    LARROW,
    DARROW,
    LPAREN,
    RPAREN,
    LBRACKET,
    RBRACKET,
    LBRACE,
    RBRACE,
    POUND,
    POUND_LBRACE,
    POUND_LT,

    DOLLAR_LPAREN,
    DOLLAR_NUM(uint),

    /* Literals */
    LIT_INT(i64, ast::int_ty),
    LIT_UINT(u64, ast::uint_ty),
    LIT_FLOAT(str_num, ast::float_ty),
    LIT_STR(str_num),
    LIT_BOOL(bool),

    /* Name components */
    IDENT(str_num, bool),
    IDX(int),
    UNDERSCORE,
    BRACEQUOTE(str_num),
    EOF,

}

fn binop_to_str(o: binop) -> str {
    alt o {
      PLUS { ret "+"; }
      MINUS { ret "-"; }
      STAR { ret "*"; }
      SLASH { ret "/"; }
      PERCENT { ret "%"; }
      CARET { ret "^"; }
      AND { ret "&"; }
      OR { ret "|"; }
      LSL { ret "<<"; }
      LSR { ret ">>"; }
      ASR { ret ">>>"; }
    }
}

fn to_str(r: reader, t: token) -> str {
    alt t {
      EQ { ret "="; }
      LT { ret "<"; }
      LE { ret "<="; }
      EQEQ { ret "=="; }
      NE { ret "!="; }
      GE { ret ">="; }
      GT { ret ">"; }
      NOT { ret "!"; }
      TILDE { ret "~"; }
      OROR { ret "||"; }
      ANDAND { ret "&&"; }
      BINOP(op) { ret binop_to_str(op); }
      BINOPEQ(op) { ret binop_to_str(op) + "="; }

      /* Structural symbols */
      AT {
        ret "@";
      }
      DOT { ret "."; }
      ELLIPSIS { ret "..."; }
      COMMA { ret ","; }
      SEMI { ret ";"; }
      COLON { ret ":"; }
      MOD_SEP { ret "::"; }
      RARROW { ret "->"; }
      LARROW { ret "<-"; }
      DARROW { ret "<->"; }
      LPAREN { ret "("; }
      RPAREN { ret ")"; }
      LBRACKET { ret "["; }
      RBRACKET { ret "]"; }
      LBRACE { ret "{"; }
      RBRACE { ret "}"; }
      POUND { ret "#"; }
      POUND_LBRACE { ret "#{"; }
      POUND_LT { ret "#<"; }

      DOLLAR_LPAREN { ret "$("; }
      DOLLAR_NUM(u) {
        ret "$" + uint::to_str(u as uint, 10u);
      }

      /* Literals */
      LIT_INT(c, ast::ty_char) {
        // FIXME: escape.
        let mut tmp = "'";
        str::push_char(tmp, c as char);
        str::push_char(tmp, '\'');
        ret tmp;
      }
      LIT_INT(i, t) {
        ret int::to_str(i as int, 10u) + ast_util::int_ty_to_str(t);
      }
      LIT_UINT(u, t) {
        ret uint::to_str(u as uint, 10u) + ast_util::uint_ty_to_str(t);
      }
      LIT_FLOAT(s, t) {
        ret interner::get::<str>(*r.interner, s) +
            ast_util::float_ty_to_str(t);
      }
      LIT_STR(s) { // FIXME: escape.
        ret "\"" + interner::get::<str>(*r.interner, s) + "\"";
      }
      LIT_BOOL(b) { if b { ret "true"; } else { ret "false"; } }

      /* Name components */
      IDENT(s, _) {
        ret interner::get::<str>(*r.interner, s);
      }
      IDX(i) { ret "_" + int::to_str(i, 10u); }
      UNDERSCORE { ret "_"; }
      BRACEQUOTE(_) { ret "<bracequote>"; }
      EOF { ret "<eof>"; }
    }
}

pure fn can_begin_expr(t: token) -> bool {
    alt t {
      LPAREN { true }
      LBRACE { true }
      LBRACKET { true }
      IDENT(_, _) { true }
      UNDERSCORE { true }
      TILDE { true }
      LIT_INT(_, _) { true }
      LIT_UINT(_, _) { true }
      LIT_FLOAT(_, _) { true }
      LIT_STR(_) { true }
      POUND { true }
      AT { true }
      NOT { true }
      BINOP(MINUS) { true }
      BINOP(STAR) { true }
      MOD_SEP { true }
      _ { false }
    }
}

// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>rustc: Fix parsing of `ret &EXPR`<commit_after>
import util::interner;
import lexer::reader;

type str_num = uint;

enum binop {
    PLUS,
    MINUS,
    STAR,
    SLASH,
    PERCENT,
    CARET,
    AND,
    OR,
    LSL,
    LSR,
    ASR,
}

enum token {
    /* Expression-operator symbols. */
    EQ,
    LT,
    LE,
    EQEQ,
    NE,
    GE,
    GT,
    ANDAND,
    OROR,
    NOT,
    TILDE,
    BINOP(binop),
    BINOPEQ(binop),

    /* Structural symbols */
    AT,
    DOT,
    ELLIPSIS,
    COMMA,
    SEMI,
    COLON,
    MOD_SEP,
    RARROW,
    LARROW,
    DARROW,
    LPAREN,
    RPAREN,
    LBRACKET,
    RBRACKET,
    LBRACE,
    RBRACE,
    POUND,
    POUND_LBRACE,
    POUND_LT,

    DOLLAR_LPAREN,
    DOLLAR_NUM(uint),

    /* Literals */
    LIT_INT(i64, ast::int_ty),
    LIT_UINT(u64, ast::uint_ty),
    LIT_FLOAT(str_num, ast::float_ty),
    LIT_STR(str_num),
    LIT_BOOL(bool),

    /* Name components */
    IDENT(str_num, bool),
    IDX(int),
    UNDERSCORE,
    BRACEQUOTE(str_num),
    EOF,

}

fn binop_to_str(o: binop) -> str {
    alt o {
      PLUS { ret "+"; }
      MINUS { ret "-"; }
      STAR { ret "*"; }
      SLASH { ret "/"; }
      PERCENT { ret "%"; }
      CARET { ret "^"; }
      AND { ret "&"; }
      OR { ret "|"; }
      LSL { ret "<<"; }
      LSR { ret ">>"; }
      ASR { ret ">>>"; }
    }
}

fn to_str(r: reader, t: token) -> str {
    alt t {
      EQ { ret "="; }
      LT { ret "<"; }
      LE { ret "<="; }
      EQEQ { ret "=="; }
      NE { ret "!="; }
      GE { ret ">="; }
      GT { ret ">"; }
      NOT { ret "!"; }
      TILDE { ret "~"; }
      OROR { ret "||"; }
      ANDAND { ret "&&"; }
      BINOP(op) { ret binop_to_str(op); }
      BINOPEQ(op) { ret binop_to_str(op) + "="; }

      /* Structural symbols */
      AT {
        ret "@";
      }
      DOT { ret "."; }
      ELLIPSIS { ret "..."; }
      COMMA { ret ","; }
      SEMI { ret ";"; }
      COLON { ret ":"; }
      MOD_SEP { ret "::"; }
      RARROW { ret "->"; }
      LARROW { ret "<-"; }
      DARROW { ret "<->"; }
      LPAREN { ret "("; }
      RPAREN { ret ")"; }
      LBRACKET { ret "["; }
      RBRACKET { ret "]"; }
      LBRACE { ret "{"; }
      RBRACE { ret "}"; }
      POUND { ret "#"; }
      POUND_LBRACE { ret "#{"; }
      POUND_LT { ret "#<"; }

      DOLLAR_LPAREN { ret "$("; }
      DOLLAR_NUM(u) {
        ret "$" + uint::to_str(u as uint, 10u);
      }

      /* Literals */
      LIT_INT(c, ast::ty_char) {
        // FIXME: escape.
        let mut tmp = "'";
        str::push_char(tmp, c as char);
        str::push_char(tmp, '\'');
        ret tmp;
      }
      LIT_INT(i, t) {
        ret int::to_str(i as int, 10u) + ast_util::int_ty_to_str(t);
      }
      LIT_UINT(u, t) {
        ret uint::to_str(u as uint, 10u) + ast_util::uint_ty_to_str(t);
      }
      LIT_FLOAT(s, t) {
        ret interner::get::<str>(*r.interner, s) +
            ast_util::float_ty_to_str(t);
      }
      LIT_STR(s) { // FIXME: escape.
        ret "\"" + interner::get::<str>(*r.interner, s) + "\"";
      }
      LIT_BOOL(b) { if b { ret "true"; } else { ret "false"; } }

      /* Name components */
      IDENT(s, _) {
        ret interner::get::<str>(*r.interner, s);
      }
      IDX(i) { ret "_" + int::to_str(i, 10u); }
      UNDERSCORE { ret "_"; }
      BRACEQUOTE(_) { ret "<bracequote>"; }
      EOF { ret "<eof>"; }
    }
}

pure fn can_begin_expr(t: token) -> bool {
    alt t {
      LPAREN { true }
      LBRACE { true }
      LBRACKET { true }
      IDENT(_, _) { true }
      UNDERSCORE { true }
      TILDE { true }
      LIT_INT(_, _) { true }
      LIT_UINT(_, _) { true }
      LIT_FLOAT(_, _) { true }
      LIT_STR(_) { true }
      POUND { true }
      AT { true }
      NOT { true }
      BINOP(MINUS) { true }
      BINOP(STAR) { true }
      BINOP(AND) { true }
      MOD_SEP { true }
      _ { false }
    }
}

// Local Variables:
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>