<commit_before>use std::borrow::Cow;

// Returns tuple (close_char, must_precede_whitespace)
fn expected_close_char_if_opens_nickname(c: char, follows_whitespace: bool) -> Option<(char, bool)> {
    let close = match c {
        '(' => Some((')', false)),
        '[' => Some((']', false)),
        '<' => Some(('>', false)),
        '“' => Some(('”', false)),
        '〝' => Some(('〞', false)),
        '‹' => Some(('›', false)),
        _ => None
    };

    if !close.is_none() {
        // Treat, e.g., opening parens as the start of a nickname
        // regardless of where it occurs
        return close;
    }

    if follows_whitespace {
        // Treat, e.g., quote character as the start of a nickname
        // only if it occurs after whitespace; otherwise, it
        // might be in-name puntuation
        match c {
            '\'' => Some(('\'', true)),
            '"' => Some(('"', true)),
            '‘' => Some(('’', true)),
            _ => None
        }
    } else {
        None
    }
}

// Optimized for the case where there is no nickname, and secondarily for the
// case where there is only one. Two or more probably means bad input.
pub fn strip_nickname(input: &str) -> Cow<str> {
    let mut nick_start_ix = 0; // This counts as not-found; we won't classify the whole string as a nickname
    let mut nick_open_char = '\0';
    let mut expected_close_char = '\0';
    let mut must_precede_whitespace = false;
    let mut prev_char = '\0';

    for (i,c) in input.char_indices() {
        if nick_start_ix == 0 {
            let close = expected_close_char_if_opens_nickname(c, prev_char.is_whitespace());
            if !close.is_none() {
                nick_start_ix = i;
                nick_open_char = c;
                expected_close_char = close.unwrap().0;
                must_precede_whitespace = close.unwrap().1
            }
        } else if c == expected_close_char {
            let j = i + c.len_utf8();
            if j >= input.len() {
                return Cow::Borrowed(&input[0..nick_start_ix]);
            }
            else if !must_precede_whitespace || input[j..].chars().nth(0).unwrap().is_whitespace()  {
                return Cow::Owned(input[0..nick_start_ix].to_string() + " " + &strip_nickname(&input[j..]));
            }
            else {
                return Cow::Owned(input[0..i].to_string() + &strip_nickname(&input[i..]));
            }
        }

        prev_char = c;
    }

    if nick_start_ix > 0 {
        if !must_precede_whitespace {
            // When there's, e.g., an opening parens, but no closing parens, strip the
            // rest of the string
            return Cow::Borrowed(&input[0..nick_start_ix]);
        } else {
            let i = nick_start_ix + nick_open_char.len_utf8();
            // Otherwise, even if there's an unmatched opening quote, don't
            // modify the string; assume an unmatched opening quote was just
            // in-name punctuation
            //
            // However, in that case, we need to check the remainder of the
            // string for actual nicknames, whose opening character we might
            // have missed while looking for the first closing character
            if i >= input.len() {
                return Cow::Borrowed(input);
            }
            else {
                return Cow::Owned(input[0..i].to_string() + &strip_nickname(&input[i..]));
            }
        }
    }

    Cow::Borrowed(input)
}
<commit_msg>Add guillemets<commit_after>use std::borrow::Cow;

// Returns tuple (close_char, must_precede_whitespace)
fn expected_close_char_if_opens_nickname(c: char, follows_whitespace: bool) -> Option<(char, bool)> {
    let close = match c {
        '(' => Some((')', false)),
        '[' => Some((']', false)),
        '<' => Some(('>', false)),
        '“' => Some(('”', false)),
        '〝' => Some(('〞', false)),
        '‹' => Some(('›', false)),
        '«' => Some(('»', false)),
        _ => None
    };

    if !close.is_none() {
        // Treat, e.g., opening parens as the start of a nickname
        // regardless of where it occurs
        return close;
    }

    if follows_whitespace {
        // Treat, e.g., quote character as the start of a nickname
        // only if it occurs after whitespace; otherwise, it
        // might be in-name puntuation
        match c {
            '\'' => Some(('\'', true)),
            '"' => Some(('"', true)),
            '‘' => Some(('’', true)),
            _ => None
        }
    } else {
        None
    }
}

// Optimized for the case where there is no nickname, and secondarily for the
// case where there is only one. Two or more probably means bad input.
pub fn strip_nickname(input: &str) -> Cow<str> {
    let mut nick_start_ix = 0; // This counts as not-found; we won't classify the whole string as a nickname
    let mut nick_open_char = '\0';
    let mut expected_close_char = '\0';
    let mut must_precede_whitespace = false;
    let mut prev_char = '\0';

    for (i,c) in input.char_indices() {
        if nick_start_ix == 0 {
            let close = expected_close_char_if_opens_nickname(c, prev_char.is_whitespace());
            if !close.is_none() {
                nick_start_ix = i;
                nick_open_char = c;
                expected_close_char = close.unwrap().0;
                must_precede_whitespace = close.unwrap().1
            }
        } else if c == expected_close_char {
            let j = i + c.len_utf8();
            if j >= input.len() {
                return Cow::Borrowed(&input[0..nick_start_ix]);
            }
            else if !must_precede_whitespace || input[j..].chars().nth(0).unwrap().is_whitespace()  {
                return Cow::Owned(input[0..nick_start_ix].to_string() + " " + &strip_nickname(&input[j..]));
            }
            else {
                return Cow::Owned(input[0..i].to_string() + &strip_nickname(&input[i..]));
            }
        }

        prev_char = c;
    }

    if nick_start_ix > 0 {
        if !must_precede_whitespace {
            // When there's, e.g., an opening parens, but no closing parens, strip the
            // rest of the string
            return Cow::Borrowed(&input[0..nick_start_ix]);
        } else {
            let i = nick_start_ix + nick_open_char.len_utf8();
            // Otherwise, even if there's an unmatched opening quote, don't
            // modify the string; assume an unmatched opening quote was just
            // in-name punctuation
            //
            // However, in that case, we need to check the remainder of the
            // string for actual nicknames, whose opening character we might
            // have missed while looking for the first closing character
            if i >= input.len() {
                return Cow::Borrowed(input);
            }
            else {
                return Cow::Owned(input[0..i].to_string() + &strip_nickname(&input[i..]));
            }
        }
    }

    Cow::Borrowed(input)
}
<|endoftext|>


<commit_before>int_module!(i32, i32);

#[test]
fn test_arith_operation() {
    let a: isize = 10;
    assert_eq!(a * (a - 1), 90);
    let i32_a: isize = 10;
    assert_eq!(i32_a, 10);
    assert_eq!(i32_a - 10, 0);
    assert_eq!(i32_a / 10, 1);
    assert_eq!(i32_a - 20, -10);
    assert_eq!(i32_a << 10, 10240);
    assert_eq!(i32_a << 16, 655360);
    assert_eq!(i32_a * 16, 160);
    assert_eq!(i32_a * i32_a * i32_a, 1000);
    assert_eq!(i32_a * i32_a * i32_a * i32_a, 10000);
    assert_eq!(i32_a * i32_a / i32_a * i32_a, 100);
    assert_eq!(i32_a * (i32_a - 1) << (2 + i32_a as usize), 368640);
    let i32_b: isize = 0x10101010;
    assert_eq!(i32_b + 1 - 1, i32_b);
    assert_eq!(i32_b << 1, i32_b << 1);
    assert_eq!(i32_b >> 1, i32_b >> 1);
    assert_eq!(i32_b & i32_b << 1, 0);
    assert_eq!(i32_b | i32_b << 1, 0x30303030);
    let i32_c: isize = 0x10101010;
    assert_eq!(i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3),
               i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3));
}
<commit_msg>Minor refactoring<commit_after>int_module!(i32, i32);

#[test]
fn test_arith_operation() {
    let a: isize = 10;
    assert_eq!(a * (a - 1), 90);
    let i32_a: isize = 10;
    assert_eq!(i32_a, 10);
    assert_eq!(i32_a - 10, 0);
    assert_eq!(i32_a / 10, 1);
    assert_eq!(i32_a - 20, -10);
    assert_eq!(i32_a << 10, 10240);
    assert_eq!(i32_a << 16, 655360);
    assert_eq!(i32_a * 16, 160);
    assert_eq!(i32_a * i32_a * i32_a, 1000);
    assert_eq!(i32_a * i32_a * i32_a * i32_a, 10000);
    assert_eq!(i32_a * i32_a / i32_a * i32_a, 100);
    assert_eq!(i32_a * (i32_a - 1) << (2 + i32_a as usize), 368640);
    let i32_b: isize = 0x10101010;
    assert_eq!(i32_b + 1 - 1, i32_b);
    assert_eq!(i32_b << 1, i32_b << 1);
    assert_eq!(i32_b >> 1, i32_b >> 1);
    assert_eq!(i32_b & i32_b << 1, 0);
    assert_eq!(i32_b | i32_b << 1, 0x30303030);
    let i32_c: isize = 0x10101010;
    assert_eq!(
        i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3),
        i32_c + i32_c * 2 / 3 * 2 + (i32_c - 7 % 3)
    );
}
<|endoftext|>


<commit_before><commit_msg>Auto merge of #690 - jrmuizel:wrench-cargo-rerun, r=Manishearth<commit_after><|endoftext|>


<commit_before>#![crate_name = "echo"]
#![feature(collections, core, old_io, rustc_private)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Derek Chiang <derekchiang93@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;

use std::old_io::{print, println};
use std::num::from_str_radix;
use std::str::from_utf8;

#[path = "../common/util.rs"]
mod util;

#[allow(dead_code)]
static NAME: &'static str = "echo";
static VERSION: &'static str = "1.0.0";

#[derive(Clone)]
struct EchoOptions {
    newline: bool,
    escape: bool
}

#[inline(always)]
fn to_char(bytes: &Vec<u8>, base: u32) -> char {
    from_str_radix::<usize>(from_utf8(bytes.as_slice()).unwrap(), base).unwrap() as u8 as char
}

#[inline(always)]
fn isxdigit(c: u8) -> bool {
    match c as char {
        '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' |
        '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' => true,
        _ => false
    }
}

#[inline(always)]
fn isodigit(c: u8) -> bool {
    match c as char {
        '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' => true,
        _ => false
    }
}

fn convert_str(string: &[u8], index: usize, base: u32) -> (char, usize) {
    let (max_digits, is_legal_digit) : (usize, fn(u8) -> bool) = match base {
        8 => (3, isodigit),
        16 => (2, isxdigit),
        _ => panic!(),
    };

    let mut bytes = vec!();
    for offset in range(0usize, max_digits) {
        if string.len() <= index + offset as usize {
            break;
        }
        let c = string[index + offset as usize];
        if is_legal_digit(c) {
            bytes.push(c as u8);
        } else {
            break;
        }
    }

    if bytes.len() == 0 {
        (' ', 0)
    } else {
        (to_char(&bytes, base), bytes.len())
    }
}

fn parse_options(args: Vec<String>, options: &mut EchoOptions) -> Option<Vec<String>> {
    let mut echo_args = vec!();
    let program = args[0].clone();
    'argloop: for arg in args.into_iter().skip(1) {
        match arg.as_slice() {
            "--help" | "-h" => {
                print_help(&program);
                return None;
            }
            "--version" | "-V" => {
                print_version();
                return None;
            }
            "-n" => options.newline = true,
            "-e" => options.escape = true,
            "-E" => options.escape = false,
            _ => {
                if arg.len() > 1 && arg.as_slice().char_at(0) == '-' {
                    let mut newopts = options.clone();
                    let argptr: *const String = &arg;  // escape from the borrow checker
                    for ch in unsafe { (*argptr).as_slice() }.chars().skip(1) {
                        match ch {
                            'h' => {
                                print_help(&program);
                                return None;
                            }
                            'V' => {
                                print_version();
                                return None;
                            }
                            'n' => newopts.newline = true,
                            'e' => newopts.escape = true,
                            'E' => newopts.escape = false,
                            _ => {
                                echo_args.push(arg);
                                continue 'argloop;
                            }
                        }
                    }
                    *options = newopts;
                } else {
                    echo_args.push(arg);
                }
            }
        }
    }
    Some(echo_args)
}

fn print_help(program: &String) {
    let opts = [
        getopts::optflag("n", "", "do not output the trailing newline"),
        getopts::optflag("e", "", "enable interpretation of backslash escapes"),
        getopts::optflag("E", "", "disable interpretation of backslash escapes (default)"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];
    println!("echo {} - display a line of text", VERSION);
    println!("");
    println!("Usage:");
    println!("  {0} [SHORT-OPTION]... [STRING]...", *program);
    println!("  {0} LONG-OPTION", *program);
    println!("");
    println(getopts::usage("Echo the STRING(s) to standard output.", &opts).as_slice());
    println("If -e is in effect, the following sequences are recognized:

\\\\      backslash
\\a      alert (BEL)
\\b      backspace
\\c      produce no further output
\\e      escape
\\f      form feed
\\n      new line
\\r      carriage return
\\t      horizontal tab
\\v      vertical tab
\\0NNN   byte with octal value NNN (1 to 3 digits)
\\xHH    byte with hexadecimal value HH (1 to 2 digits)");
}

fn print_version() {
    println!("echo version: {}", VERSION);
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut options = EchoOptions {
        newline: false,
        escape: false
    };

    let free = match parse_options(args, &mut options) {
        Some(vec) => vec,
        None => return 0
    };

    if !free.is_empty() {
        let string = free.connect(" ");
        if options.escape {
            let mut prev_was_slash = false;
            let mut iter = string.as_slice().chars().enumerate();
            loop {
                match iter.next() {
                    Some((index, c)) => {
                        if !prev_was_slash {
                            if c != '\\' {
                                print!("{}", c);
                            } else {
                                prev_was_slash = true;
                            }
                        } else {
                            prev_was_slash = false;
                            match c {
                                '\\' => print!("\\"),
                                'a' => print!("\x07"),
                                'b' => print!("\x08"),
                                'c' => break,
                                'e' => print!("\x1B"),
                                'f' => print!("\x0C"),
                                'n' => print!("\n"),
                                'r' => print!("\r"),
                                't' => print!("\t"),
                                'v' => print!("\x0B"),
                                'x' => {
                                    let (c, num_char_used) = convert_str(string.as_bytes(), index + 1, 16);
                                    if num_char_used == 0 {
                                        print!("\\x");
                                    } else {
                                        print!("{}", c);
                                        for _ in range(0, num_char_used) {
                                            iter.next(); // consume used characters
                                        }
                                    }
                                },
                                '0' => {
                                    let (c, num_char_used) = convert_str(string.as_bytes(), index + 1, 8);
                                    if num_char_used == 0 {
                                        print!("\0");
                                    } else {
                                        print!("{}", c);
                                        for _ in range(0, num_char_used) {
                                            iter.next(); // consume used characters
                                        }
                                    }
                                }
                                _ => {
                                    let (esc_c, num_char_used) = convert_str(string.as_bytes(), index, 8);
                                    if num_char_used == 0 {
                                        print!("\\{}", c);
                                    } else {
                                        print!("{}", esc_c);
                                        for _ in range(1, num_char_used) {
                                            iter.next(); // consume used characters
                                        }
                                    }
                                }
                            }
                        }
                    }
                    None => break
                }
            }
        } else {
            print(string.as_slice());
        }
    }

    if !options.newline {
        println!("")
    }

    0
}
<commit_msg>Upgrade echo to use recent Rust nightly build.<commit_after>#![crate_name = "echo"]
#![feature(rustc_private, str_char)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Derek Chiang <derekchiang93@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
extern crate libc;

use std::str::from_utf8;

#[path = "../common/util.rs"]
mod util;

#[allow(dead_code)]
static NAME: &'static str = "echo";
static VERSION: &'static str = "1.0.0";

#[derive(Clone)]
struct EchoOptions {
    newline: bool,
    escape: bool
}

#[inline(always)]
fn to_char(bytes: &Vec<u8>, base: u32) -> char {
    usize::from_str_radix(from_utf8(bytes.as_ref()).unwrap(), base).unwrap() as u8 as char
}

#[inline(always)]
fn isxdigit(c: u8) -> bool {
    match c as char {
        '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' |
        '8' | '9' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' => true,
        _ => false
    }
}

#[inline(always)]
fn isodigit(c: u8) -> bool {
    match c as char {
        '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' => true,
        _ => false
    }
}

fn convert_str(string: &[u8], index: usize, base: u32) -> (char, usize) {
    let (max_digits, is_legal_digit) : (usize, fn(u8) -> bool) = match base {
        8 => (3, isodigit),
        16 => (2, isxdigit),
        _ => panic!(),
    };

    let mut bytes = vec!();
    for offset in (0usize .. max_digits) {
        if string.len() <= index + offset as usize {
            break;
        }
        let c = string[index + offset as usize];
        if is_legal_digit(c) {
            bytes.push(c as u8);
        } else {
            break;
        }
    }

    if bytes.len() == 0 {
        (' ', 0)
    } else {
        (to_char(&bytes, base), bytes.len())
    }
}

fn parse_options(args: Vec<String>, options: &mut EchoOptions) -> Option<Vec<String>> {
    let mut echo_args = vec!();
    let program = args[0].clone();
    'argloop: for arg in args.into_iter().skip(1) {
        match arg.as_ref() {
            "--help" | "-h" => {
                print_help(&program);
                return None;
            }
            "--version" | "-V" => {
                print_version();
                return None;
            }
            "-n" => options.newline = true,
            "-e" => options.escape = true,
            "-E" => options.escape = false,
            _ => {
                if arg.len() > 1 && arg.char_at(0) == '-' {
                    let mut newopts = options.clone();
                    for ch in arg.chars().skip(1) {
                        match ch {
                            'h' => {
                                print_help(&program);
                                return None;
                            }
                            'V' => {
                                print_version();
                                return None;
                            }
                            'n' => newopts.newline = true,
                            'e' => newopts.escape = true,
                            'E' => newopts.escape = false,
                            _ => {
                                echo_args.push(arg.clone());
                                continue 'argloop;
                            }
                        }
                    }
                    *options = newopts;
                } else {
                    echo_args.push(arg);
                }
            }
        }
    }
    Some(echo_args)
}

fn print_help(program: &String) {
    let opts = [
        getopts::optflag("n", "", "do not output the trailing newline"),
        getopts::optflag("e", "", "enable interpretation of backslash escapes"),
        getopts::optflag("E", "", "disable interpretation of backslash escapes (default)"),
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];
    println!("echo {} - display a line of text", VERSION);
    println!("");
    println!("Usage:");
    println!("  {0} [SHORT-OPTION]... [STRING]...", *program);
    println!("  {0} LONG-OPTION", *program);
    println!("");
    println!("{}", getopts::usage("Echo the STRING(s) to standard output.", &opts));
    println!("{}", "If -e is in effect, the following sequences are recognized:

\\\\      backslash
\\a      alert (BEL)
\\b      backspace
\\c      produce no further output
\\e      escape
\\f      form feed
\\n      new line
\\r      carriage return
\\t      horizontal tab
\\v      vertical tab
\\0NNN   byte with octal value NNN (1 to 3 digits)
\\xHH    byte with hexadecimal value HH (1 to 2 digits)");
}

fn print_version() {
    println!("echo version: {}", VERSION);
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut options = EchoOptions {
        newline: false,
        escape: false
    };

    let free = match parse_options(args, &mut options) {
        Some(vec) => vec,
        None => return 0
    };

    if !free.is_empty() {
        let string = free.connect(" ");
        if options.escape {
            let mut prev_was_slash = false;
            let mut iter = string.chars().enumerate();
            loop {
                match iter.next() {
                    Some((index, c)) => {
                        if !prev_was_slash {
                            if c != '\\' {
                                print!("{}", c);
                            } else {
                                prev_was_slash = true;
                            }
                        } else {
                            prev_was_slash = false;
                            match c {
                                '\\' => print!("\\"),
                                'a' => print!("\x07"),
                                'b' => print!("\x08"),
                                'c' => break,
                                'e' => print!("\x1B"),
                                'f' => print!("\x0C"),
                                'n' => print!("\n"),
                                'r' => print!("\r"),
                                't' => print!("\t"),
                                'v' => print!("\x0B"),
                                'x' => {
                                    let (c, num_char_used) = convert_str(string.as_bytes(), index + 1, 16);
                                    if num_char_used == 0 {
                                        print!("\\x");
                                    } else {
                                        print!("{}", c);
                                        for _ in (0 .. num_char_used) {
                                            iter.next(); // consume used characters
                                        }
                                    }
                                },
                                '0' => {
                                    let (c, num_char_used) = convert_str(string.as_bytes(), index + 1, 8);
                                    if num_char_used == 0 {
                                        print!("\0");
                                    } else {
                                        print!("{}", c);
                                        for _ in (0 .. num_char_used) {
                                            iter.next(); // consume used characters
                                        }
                                    }
                                }
                                _ => {
                                    let (esc_c, num_char_used) = convert_str(string.as_bytes(), index, 8);
                                    if num_char_used == 0 {
                                        print!("\\{}", c);
                                    } else {
                                        print!("{}", esc_c);
                                        for _ in (1 .. num_char_used) {
                                            iter.next(); // consume used characters
                                        }
                                    }
                                }
                            }
                        }
                    }
                    None => break
                }
            }
        } else {
            print!("{}", string);
        }
    }

    if !options.newline {
        println!("")
    }

    0
}
<|endoftext|>


<commit_before>use criterion::Criterion;
use lucet_runtime_internals::context::{Context, ContextHandle};

/// Time the initialization of a context.
fn context_init(c: &mut Criterion) {
    extern "C" fn f() {}

    let mut stack = vec![0u64; 1024].into_boxed_slice();

    c.bench_function("context_init", move |b| {
        b.iter(|| {
            let mut parent = ContextHandle::new();
            ContextHandle::create_and_init(
                &mut *stack,
                &mut parent,
                f as *const extern "C" fn(),
                &[],
            )
            .unwrap();
        })
    });
}

/// Time the swap from an already-initialized context to a guest function and back.
fn context_swap_return(c: &mut Criterion) {
    extern "C" fn f() {}

    c.bench_function("context_swap_return", move |b| {
        b.iter_batched(
            || {
                let mut stack = vec![0u64; 1024].into_boxed_slice();
                let mut parent = ContextHandle::new();
                let child = ContextHandle::create_and_init(
                    &mut *stack,
                    &mut parent,
                    f as *const extern "C" fn(),
                    &[],
                )
                .unwrap();
                (stack, parent, child)
            },
            |(stack, mut parent, child)| unsafe {
                Context::swap(&mut parent, &child);
                stack
            },
            criterion::BatchSize::PerIteration,
        )
    });
}

/// Swap to a trivial guest function that takes a bunch of arguments.
fn context_swap_return_many_args(c: &mut Criterion) {
    extern "C" fn f(
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
    ) {
    }

    let args = vec![
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
    ];

    c.bench_function("context_swap_return_many_args", move |b| {
        b.iter_batched(
            || {
                let mut stack = vec![0u64; 1024].into_boxed_slice();
                let mut parent = ContextHandle::new();
                let child = ContextHandle::create_and_init(
                    &mut *stack,
                    &mut parent,
                    f as *const extern "C" fn(),
                    &args,
                )
                .unwrap();
                (stack, parent, child)
            },
            |(stack, mut parent, child)| unsafe {
                Context::swap(&mut parent, &child);
                stack
            },
            criterion::BatchSize::PerIteration,
        )
    });
}

/// Time the call to sigprocmask as used in `Context::init()`.
fn context_sigprocmask(c: &mut Criterion) {
    use nix::sys::signal;
    c.bench_function("context_sigprocmask", |b| {
        b.iter_batched(
            || signal::SigSet::empty(),
            |mut sigset| {
                signal::sigprocmask(signal::SigmaskHow::SIG_SETMASK, None, Some(&mut sigset))
                    .unwrap()
            },
            criterion::BatchSize::PerIteration,
        )
    });
}

pub fn context_benches(c: &mut Criterion) {
    context_init(c);
    context_swap_return(c);
    context_swap_return_many_args(c);
    context_sigprocmask(c);
}
<commit_msg>[lucet-benchmarks] add cases that combine context init and swap<commit_after>use criterion::Criterion;
use lucet_runtime_internals::context::{Context, ContextHandle};

/// Time the initialization of a context.
fn context_init(c: &mut Criterion) {
    extern "C" fn f() {}

    let mut stack = vec![0u64; 1024].into_boxed_slice();

    c.bench_function("context_init", move |b| {
        b.iter(|| {
            let mut parent = ContextHandle::new();
            ContextHandle::create_and_init(
                &mut *stack,
                &mut parent,
                f as *const extern "C" fn(),
                &[],
            )
            .unwrap();
        })
    });
}

/// Time the swap from an already-initialized context to a guest function and back.
fn context_swap_return(c: &mut Criterion) {
    extern "C" fn f() {}

    c.bench_function("context_swap_return", move |b| {
        b.iter_batched(
            || {
                let mut stack = vec![0u64; 1024].into_boxed_slice();
                let mut parent = ContextHandle::new();
                let child = ContextHandle::create_and_init(
                    &mut *stack,
                    &mut parent,
                    f as *const extern "C" fn(),
                    &[],
                )
                .unwrap();
                (stack, parent, child)
            },
            |(stack, mut parent, child)| unsafe {
                Context::swap(&mut parent, &child);
                stack
            },
            criterion::BatchSize::PerIteration,
        )
    });
}

/// Time initialization plus swap and return.
fn context_init_swap_return(c: &mut Criterion) {
    extern "C" fn f() {}

    c.bench_function("context_init_swap_return", move |b| {
        b.iter_batched(
            || vec![0u64; 1024].into_boxed_slice(),
            |mut stack| {
                let mut parent = ContextHandle::new();
                let child = ContextHandle::create_and_init(
                    &mut *stack,
                    &mut parent,
                    f as *const extern "C" fn(),
                    &[],
                )
                .unwrap();
                unsafe { Context::swap(&mut parent, &child) };
                stack
            },
            criterion::BatchSize::PerIteration,
        )
    });
}

/// Swap to a trivial guest function that takes a bunch of arguments.
fn context_init_swap_return_many_args(c: &mut Criterion) {
    extern "C" fn f(
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
        _: u8,
        _: u16,
        _: u32,
        _: u64,
        _: f32,
        _: f64,
    ) {
    }

    let args = vec![
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
        0xAFu8.into(),
        0xAFu16.into(),
        0xAFu32.into(),
        0xAFu64.into(),
        175.0f32.into(),
        175.0f64.into(),
    ];

    c.bench_function("context_init_swap_return_many_args", move |b| {
        b.iter_batched(
            || vec![0u64; 1024].into_boxed_slice(),
            |mut stack| {
                let mut parent = ContextHandle::new();
                let child = ContextHandle::create_and_init(
                    &mut *stack,
                    &mut parent,
                    f as *const extern "C" fn(),
                    &args,
                )
                .unwrap();
                unsafe { Context::swap(&mut parent, &child) };
                stack
            },
            criterion::BatchSize::PerIteration,
        )
    });
}

/// Time the call to sigprocmask as used in `Context::init()`.
fn context_sigprocmask(c: &mut Criterion) {
    use nix::sys::signal;
    c.bench_function("context_sigprocmask", |b| {
        b.iter_batched(
            || signal::SigSet::empty(),
            |mut sigset| {
                signal::sigprocmask(signal::SigmaskHow::SIG_SETMASK, None, Some(&mut sigset))
                    .unwrap()
            },
            criterion::BatchSize::PerIteration,
        )
    });
}

pub fn context_benches(c: &mut Criterion) {
    context_init(c);
    context_swap_return(c);
    context_init_swap_return(c);
    context_init_swap_return_many_args(c);
    context_sigprocmask(c);
}
<|endoftext|>


<commit_before>#![cfg(target_os = "linux")]

mod common;

use std::time::{Duration, Instant};

use common::cleanup;

#[test]
fn test_quiescent_cpu_time() {
    const DB_DIR: &str = "sleeper";
    cleanup(DB_DIR);

    fn run() {
        let start = Instant::now();
        let db = sled::Db::open(DB_DIR).unwrap();
        std::thread::sleep(Duration::from_secs(10));
        drop(db);
        let end = Instant::now();

        let (user_cpu_time, system_cpu_time) = unsafe {
            let mut resource_usage: libc::rusage = std::mem::zeroed();
            let return_value = libc::getrusage(
                libc::RUSAGE_SELF,
                (&mut resource_usage) as *mut libc::rusage,
            );
            if return_value != 0 {
                panic!("error {} from getrusage()", *libc::__errno_location());
            }
            (resource_usage.ru_utime, resource_usage.ru_stime)
        };

        let user_cpu_seconds =
            user_cpu_time.tv_sec as f64 + user_cpu_time.tv_usec as f64 * 1e-6;
        let system_cpu_seconds = system_cpu_time.tv_sec as f64
            + system_cpu_time.tv_usec as f64 * 1e-6;
        let real_time_elapsed = end.duration_since(start);

        if user_cpu_seconds + system_cpu_seconds > 1.0 {
            panic!(
                "Database used too much CPU during a quiescent workload. User: {}s, system: {}s (wall clock: {}s)",
                user_cpu_seconds,
                system_cpu_seconds,
                real_time_elapsed.as_secs_f64(),
            );
        }
    }

    let child = unsafe { libc::fork() };
    if child == 0 {
        common::setup_logger();
        if let Err(e) = std::thread::spawn(run).join() {
            println!("test failed: {:?}", e);
            std::process::exit(15);
        } else {
            std::process::exit(0);
        }
    } else {
        let mut status = 0;
        unsafe {
            libc::waitpid(child, &mut status as *mut libc::c_int, 0);
        }
        if status != 0 {
            cleanup(DB_DIR);
            panic!("child exited abnormally");
        }
    }

    cleanup(DB_DIR);
}
<commit_msg>Fix deprecation warning in new test<commit_after>#![cfg(target_os = "linux")]

mod common;

use std::time::{Duration, Instant};

use common::cleanup;

#[test]
fn test_quiescent_cpu_time() {
    const DB_DIR: &str = "sleeper";
    cleanup(DB_DIR);

    fn run() {
        let start = Instant::now();
        let db = sled::open(DB_DIR).unwrap();
        std::thread::sleep(Duration::from_secs(10));
        drop(db);
        let end = Instant::now();

        let (user_cpu_time, system_cpu_time) = unsafe {
            let mut resource_usage: libc::rusage = std::mem::zeroed();
            let return_value = libc::getrusage(
                libc::RUSAGE_SELF,
                (&mut resource_usage) as *mut libc::rusage,
            );
            if return_value != 0 {
                panic!("error {} from getrusage()", *libc::__errno_location());
            }
            (resource_usage.ru_utime, resource_usage.ru_stime)
        };

        let user_cpu_seconds =
            user_cpu_time.tv_sec as f64 + user_cpu_time.tv_usec as f64 * 1e-6;
        let system_cpu_seconds = system_cpu_time.tv_sec as f64
            + system_cpu_time.tv_usec as f64 * 1e-6;
        let real_time_elapsed = end.duration_since(start);

        if user_cpu_seconds + system_cpu_seconds > 1.0 {
            panic!(
                "Database used too much CPU during a quiescent workload. User: {}s, system: {}s (wall clock: {}s)",
                user_cpu_seconds,
                system_cpu_seconds,
                real_time_elapsed.as_secs_f64(),
            );
        }
    }

    let child = unsafe { libc::fork() };
    if child == 0 {
        common::setup_logger();
        if let Err(e) = std::thread::spawn(run).join() {
            println!("test failed: {:?}", e);
            std::process::exit(15);
        } else {
            std::process::exit(0);
        }
    } else {
        let mut status = 0;
        unsafe {
            libc::waitpid(child, &mut status as *mut libc::c_int, 0);
        }
        if status != 0 {
            cleanup(DB_DIR);
            panic!("child exited abnormally");
        }
    }

    cleanup(DB_DIR);
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::path::{Path};
use std::fs::{self, File};
use rand::StdRng;
use rand::SeedableRng;
use std::iter::Filter;
use calx::Dijkstra;
use entity::Entity;
use ecs::EntityIter;
use world;
use flags;
use calx::Dir6;
use area::Area;
use location::Location;
use ecs::{ComponentAccess};
use mapgen::{Biome, AreaSpec};
use ::{Msg};
use msg;

/// Game update control.
#[derive(Copy, Clone, PartialEq)]
pub enum ControlState {
    AwaitingInput,
    ReadyToUpdate,
}

/// Player input action.
#[derive(Copy, Eq, PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum Input {
    /// Take a step in the given direction.
    Step(Dir6),
    /// Melee attack in the given direction.
    Melee(Dir6),
    /// Shoot in the given direction.
    Shoot(Dir6),
    /// Do nothing for a turn.
    Pass,
}

/// Return the player entity if one exists.
pub fn player() -> Option<Entity> {
    world::with(|w| w.flags.player)
}

/// Return true if the game has ended and the player can make no further
/// actions.
pub fn is_game_over() -> bool {
    player().is_none()
}

/// Find the first entity that has a local (not inherited) Desc component with
/// the given name.
pub fn find_prototype(name: &str) -> Option<Entity> {
    world::with(|w|
        entities().find(|&e| {
            if let Some(d) = w.descs().get_local(e) {
                if d.name == name { return true; }
            }
            false
        })
    )
}

/// Spawn a specific type of entity
pub fn spawn_named(name: &str, loc: Location) {
    find_prototype(name).expect(&format!("Spawn prototype '{}' not found", name)[..])
        .clone_at(loc);
}

// World update state machine //////////////////////////////////////////

/// Get the current control state.
pub fn control_state() -> ControlState {
    if world::with(|w| w.flags.player_acted) { return ControlState::ReadyToUpdate; }
    match player() {
        Some(p) if p.acts_this_frame() => ControlState::AwaitingInput,
        _ => ControlState::ReadyToUpdate,
    }
}

/// Top-level game state update function. Only valid to call if
/// control_state() returned ReadyToUpdate.
pub fn update() {
    assert!(control_state() == ControlState::ReadyToUpdate);

    ai_main();

    world::with_mut(|w| {
        w.flags.tick += 1;
        w.flags.player_acted = false;
    });
}

/// Give player input. Only valid to call if control_state() returned
/// AwaitingInput.
pub fn input(input: Input) {
    assert!(control_state() == ControlState::AwaitingInput);
    let p = player().expect("No player to receive input");
    match input {
        Input::Step(d) => {
            p.step(d);
        }
        Input::Melee(d) => {
            p.melee(d);
        }
        Input::Shoot(d) => {
            p.shoot(d);
        }
        Input::Pass => {
        }
    }
    world::with_mut(|w| w.flags.player_acted = true);

    // Run one world update cycle right away, so that we don't get awkward
    // single frames rendered where the player has acted and the rest of the
    // world hasn't.
    if control_state() == ControlState::ReadyToUpdate {
        update();
    }
}

// Entities ////////////////////////////////////////////////////////////

/// Return an iterator of all the world entities.
pub fn entities() -> EntityIter {
    world::with(|w| w.ecs.iter())
}

/// Return an iterator of all the world mobs.
pub fn _mobs() -> Filter<EntityIter, fn(&Entity) -> bool> {
    fn _is_mob(e: &Entity) -> bool { e.is_mob() }
    entities().filter(_is_mob)
}

/// Run AI for all autonomous mobs.
fn ai_main() {
    for entity in entities() {
        entity.update();
    }
}

// World logic /////////////////////////////////////////////////////////

/// Return the current floor depth. Greater depths mean more powerful monsters
/// and stranger terrain.
pub fn current_depth() -> i32 { world::with(|w| w.area.seed.spec.depth) }

pub fn start_level(depth: i32) {
    let biome = match depth {
        1 => Biome::Overland,
        _ => Biome::Dungeon,
    };

    clear_nonplayers();

    let seed = world::with(|w| w.flags.seed);

    let new_area = Area::new(
        seed,
        AreaSpec::new(biome, depth));
    // XXX: How to move area into the closure without cloning?
    world::with_mut(|w| {
        w.area = new_area.clone();
    });

    let mut rng: StdRng = SeedableRng::from_seed(&[seed as usize + depth as usize][..]);
    for (spawn, loc) in world::with(|w| w.area.get_spawns()).into_iter() {
        spawn.spawn(&mut rng, loc);
    }

    let start_loc = world::with(|w| w.area.player_entrance());
    // Either reuse the existing player or create a new one.
    match player() {
        Some(p) => {
            p.forget_map();
            p.place(start_loc);
        }
        None => {
            let player = find_prototype("player").expect("No Player prototype found!")
            .clone_at(start_loc);
            world::with_mut(|w| w.flags.player = Some(player));
        }
    };
    flags::set_camera(start_loc);
}

fn clear_nonplayers() {
    let po = player();
    for e in entities() {
        // Don't destroy player or player's inventory.
        if let Some(p) = po {
            if e == p || p.contains(e) {
                continue;
            }
        }

        if e.location().is_some() {
            e.delete();
        }
    }
}

/// Move the player to the next level.
pub fn next_level() {
    // This is assuming a really simple, original Rogue style descent-only, no
    // persistent maps style world.
    start_level(current_depth() + 1);
    caption!("Depth {}", current_depth() - 1);
}

// Effects /////////////////////////////////////////////////////////////

/// Create a projectile arc in dir from origin.
pub fn shoot(origin: Location, dir: Dir6, range: u32, power: i32) {
    let mut loc = origin;
    if range == 0 { return; }
    for i in 1..(range + 1) {
        loc = origin + dir.to_v2() * (i as i32);
        if loc.terrain().blocks_shot() {
            msg::push(::Msg::Sparks(loc));
            break;
        }
        if let Some(e) = loc.mob_at() {
            e.damage(power);
            break;
        }
    }
    msg::push(::Msg::Beam(origin, loc));
}

/// Generate an explosion at location.
pub fn explode(center: Location, power: i32) {
    // Add more complex parametrization if needed.
    msg::push(Msg::Explosion(center));

    // Damage the center.
    if let Some(e) = center.mob_at() {
        e.damage(power);
    }

    for d in Dir6::iter() {
        if let Some(e) = (center + d.to_v2()).mob_at() {
            // Explosions with enough power push back mobs.
            // TODO: Pushback might consider mob size, big guys get pushed
            // around less.
            let push_threshold = 4;
            if power >= push_threshold {
                e.push(*d, ((power - push_threshold) / 2 + 1) as u32);
            }
            if e.exists() {
                e.damage(power);
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////

/// Build a Dijkstra map towards the unexplored corners of the player's FOV.
///
/// Pathing_depth is the depth of the search map. Low pathing depths may not
/// reach distant unexplored cells, but high pathing depths take longer to
/// calculate.
pub fn autoexplore_map(pathing_depth: u32) -> Option<Dijkstra<Location>> {
    let locs = world::with(|w| w.area.terrain.iter()
                           .map(|(&loc, _)| loc)
                           .filter(|loc| loc.fov_status().is_none())
                           .collect::<Vec<Location>>());

    if locs.len() == 0 {
        return None;
    }

    Some(Dijkstra::new(locs, |&loc| !loc.blocks_walk(), pathing_depth))
}

/// Look for targets to shoot in a direction.
pub fn find_target(shooter: Entity, dir: Dir6, range: usize) -> Option<Entity> {
    let origin = shooter.location().unwrap();
    for i in 1..(range + 1) {
        let loc = origin + dir.to_v2() * (i as i32);
        if loc.terrain().blocks_shot() {
            break;
        }
        if let Some(e) = loc.mob_at() {
            if shooter.is_hostile_to(e) { return Some(e); }
        }
    }
    None
}

////////////////////////////////////////////////////////////////////////

pub fn save_game() {
    // Only save if there's still a living player around.
    if is_game_over() {
        return;
    }

    let save_data = world::save();
    File::create("magog_save.json").unwrap()
        .write_all(&save_data.into_bytes()).unwrap();
}

pub fn load_game() {
    let path = Path::new("magog_save.json");
    if !path.exists() { return; }
    let mut save_data = String::new();
    File::open(&path).unwrap().read_to_string(&mut save_data).unwrap();
    // TODO: Handle failed load nicely.
    world::load(&save_data[..]).unwrap();
}

pub fn _delete_save() {
    let _ = fs::remove_file("magog_save.json");
}

pub fn _save_exists() -> bool  { Path::new("magog_save.json").exists() }
<commit_msg>Stable savefile handling<commit_after>use std::io::prelude::*;
use std::path::{Path};
use std::fs::{self, File};
use rand::StdRng;
use rand::SeedableRng;
use std::iter::Filter;
use calx::Dijkstra;
use entity::Entity;
use ecs::EntityIter;
use world;
use flags;
use calx::Dir6;
use area::Area;
use location::Location;
use ecs::{ComponentAccess};
use mapgen::{Biome, AreaSpec};
use ::{Msg};
use msg;

/// Game update control.
#[derive(Copy, Clone, PartialEq)]
pub enum ControlState {
    AwaitingInput,
    ReadyToUpdate,
}

/// Player input action.
#[derive(Copy, Eq, PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum Input {
    /// Take a step in the given direction.
    Step(Dir6),
    /// Melee attack in the given direction.
    Melee(Dir6),
    /// Shoot in the given direction.
    Shoot(Dir6),
    /// Do nothing for a turn.
    Pass,
}

/// Return the player entity if one exists.
pub fn player() -> Option<Entity> {
    world::with(|w| w.flags.player)
}

/// Return true if the game has ended and the player can make no further
/// actions.
pub fn is_game_over() -> bool {
    player().is_none()
}

/// Find the first entity that has a local (not inherited) Desc component with
/// the given name.
pub fn find_prototype(name: &str) -> Option<Entity> {
    world::with(|w|
        entities().find(|&e| {
            if let Some(d) = w.descs().get_local(e) {
                if d.name == name { return true; }
            }
            false
        })
    )
}

/// Spawn a specific type of entity
pub fn spawn_named(name: &str, loc: Location) {
    find_prototype(name).expect(&format!("Spawn prototype '{}' not found", name)[..])
        .clone_at(loc);
}

// World update state machine //////////////////////////////////////////

/// Get the current control state.
pub fn control_state() -> ControlState {
    if world::with(|w| w.flags.player_acted) { return ControlState::ReadyToUpdate; }
    match player() {
        Some(p) if p.acts_this_frame() => ControlState::AwaitingInput,
        _ => ControlState::ReadyToUpdate,
    }
}

/// Top-level game state update function. Only valid to call if
/// control_state() returned ReadyToUpdate.
pub fn update() {
    assert!(control_state() == ControlState::ReadyToUpdate);

    ai_main();

    world::with_mut(|w| {
        w.flags.tick += 1;
        w.flags.player_acted = false;
    });
}

/// Give player input. Only valid to call if control_state() returned
/// AwaitingInput.
pub fn input(input: Input) {
    assert!(control_state() == ControlState::AwaitingInput);
    let p = player().expect("No player to receive input");
    match input {
        Input::Step(d) => {
            p.step(d);
        }
        Input::Melee(d) => {
            p.melee(d);
        }
        Input::Shoot(d) => {
            p.shoot(d);
        }
        Input::Pass => {
        }
    }
    world::with_mut(|w| w.flags.player_acted = true);

    // Run one world update cycle right away, so that we don't get awkward
    // single frames rendered where the player has acted and the rest of the
    // world hasn't.
    if control_state() == ControlState::ReadyToUpdate {
        update();
    }
}

// Entities ////////////////////////////////////////////////////////////

/// Return an iterator of all the world entities.
pub fn entities() -> EntityIter {
    world::with(|w| w.ecs.iter())
}

/// Return an iterator of all the world mobs.
pub fn _mobs() -> Filter<EntityIter, fn(&Entity) -> bool> {
    fn _is_mob(e: &Entity) -> bool { e.is_mob() }
    entities().filter(_is_mob)
}

/// Run AI for all autonomous mobs.
fn ai_main() {
    for entity in entities() {
        entity.update();
    }
}

// World logic /////////////////////////////////////////////////////////

/// Return the current floor depth. Greater depths mean more powerful monsters
/// and stranger terrain.
pub fn current_depth() -> i32 { world::with(|w| w.area.seed.spec.depth) }

pub fn start_level(depth: i32) {
    let biome = match depth {
        1 => Biome::Overland,
        _ => Biome::Dungeon,
    };

    clear_nonplayers();

    let seed = world::with(|w| w.flags.seed);

    let new_area = Area::new(
        seed,
        AreaSpec::new(biome, depth));
    // XXX: How to move area into the closure without cloning?
    world::with_mut(|w| {
        w.area = new_area.clone();
    });

    let mut rng: StdRng = SeedableRng::from_seed(&[seed as usize + depth as usize][..]);
    for (spawn, loc) in world::with(|w| w.area.get_spawns()).into_iter() {
        spawn.spawn(&mut rng, loc);
    }

    let start_loc = world::with(|w| w.area.player_entrance());
    // Either reuse the existing player or create a new one.
    match player() {
        Some(p) => {
            p.forget_map();
            p.place(start_loc);
        }
        None => {
            let player = find_prototype("player").expect("No Player prototype found!")
            .clone_at(start_loc);
            world::with_mut(|w| w.flags.player = Some(player));
        }
    };
    flags::set_camera(start_loc);
}

fn clear_nonplayers() {
    let po = player();
    for e in entities() {
        // Don't destroy player or player's inventory.
        if let Some(p) = po {
            if e == p || p.contains(e) {
                continue;
            }
        }

        if e.location().is_some() {
            e.delete();
        }
    }
}

/// Move the player to the next level.
pub fn next_level() {
    // This is assuming a really simple, original Rogue style descent-only, no
    // persistent maps style world.
    start_level(current_depth() + 1);
    caption!("Depth {}", current_depth() - 1);
}

// Effects /////////////////////////////////////////////////////////////

/// Create a projectile arc in dir from origin.
pub fn shoot(origin: Location, dir: Dir6, range: u32, power: i32) {
    let mut loc = origin;
    if range == 0 { return; }
    for i in 1..(range + 1) {
        loc = origin + dir.to_v2() * (i as i32);
        if loc.terrain().blocks_shot() {
            msg::push(::Msg::Sparks(loc));
            break;
        }
        if let Some(e) = loc.mob_at() {
            e.damage(power);
            break;
        }
    }
    msg::push(::Msg::Beam(origin, loc));
}

/// Generate an explosion at location.
pub fn explode(center: Location, power: i32) {
    // Add more complex parametrization if needed.
    msg::push(Msg::Explosion(center));

    // Damage the center.
    if let Some(e) = center.mob_at() {
        e.damage(power);
    }

    for d in Dir6::iter() {
        if let Some(e) = (center + d.to_v2()).mob_at() {
            // Explosions with enough power push back mobs.
            // TODO: Pushback might consider mob size, big guys get pushed
            // around less.
            let push_threshold = 4;
            if power >= push_threshold {
                e.push(*d, ((power - push_threshold) / 2 + 1) as u32);
            }
            if e.exists() {
                e.damage(power);
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////

/// Build a Dijkstra map towards the unexplored corners of the player's FOV.
///
/// Pathing_depth is the depth of the search map. Low pathing depths may not
/// reach distant unexplored cells, but high pathing depths take longer to
/// calculate.
pub fn autoexplore_map(pathing_depth: u32) -> Option<Dijkstra<Location>> {
    let locs = world::with(|w| w.area.terrain.iter()
                           .map(|(&loc, _)| loc)
                           .filter(|loc| loc.fov_status().is_none())
                           .collect::<Vec<Location>>());

    if locs.len() == 0 {
        return None;
    }

    Some(Dijkstra::new(locs, |&loc| !loc.blocks_walk(), pathing_depth))
}

/// Look for targets to shoot in a direction.
pub fn find_target(shooter: Entity, dir: Dir6, range: usize) -> Option<Entity> {
    let origin = shooter.location().unwrap();
    for i in 1..(range + 1) {
        let loc = origin + dir.to_v2() * (i as i32);
        if loc.terrain().blocks_shot() {
            break;
        }
        if let Some(e) = loc.mob_at() {
            if shooter.is_hostile_to(e) { return Some(e); }
        }
    }
    None
}

////////////////////////////////////////////////////////////////////////

static SAVE_FILENAME: &'static str = "magog_save.json";

pub fn save_game() {
    // Only save if there's still a living player around.
    if is_game_over() {
        return;
    }

    let save_data = world::save();
    File::create(SAVE_FILENAME).unwrap()
        .write_all(&save_data.into_bytes()).unwrap();
}

pub fn load_game() {
    if !save_exists() { return; }
    let path = Path::new(SAVE_FILENAME);
    let mut save_data = String::new();
    File::open(&path).unwrap().read_to_string(&mut save_data).unwrap();
    // TODO: Handle failed load nicely.
    world::load(&save_data[..]).unwrap();
}

pub fn _delete_save() {
    let _ = fs::remove_file(SAVE_FILENAME);
}

pub fn save_exists() -> bool { fs::metadata(SAVE_FILENAME).is_ok() }
<|endoftext|>


<commit_before>//! [한국 러스트 사용자 그룹 홈페이지][rust-kr] 소스코드
//! --------
//!
//! ### 사용법
//! ```bash
//! git clone https://github.com/rust-kr/rust-kr.org.wiki.git docs
//! cargo run
//! # 웹 브라우저에서 http://localhost:8000 를 열어보세요
//! ```
//!
//! [rust-kr]: http://rust-kr.org

// 한국 러스트 사용자 그룹 홈페이지
// Copyright (C) 2016  Hyeon Kim
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#[macro_use(itry)] extern crate iron;
#[macro_use(router)] extern crate router;
extern crate staticfile;
extern crate handlebars_iron as hbs;
extern crate pulldown_cmark as cmark;

use std::collections::BTreeMap;
use iron::prelude::*;
use iron::status;
use iron::middleware::{Handler, AfterMiddleware};
use staticfile::Static;
use hbs::{Template, HandlebarsEngine, DirectorySource};

//
// Configs
//
/// 서버가 소켓을 열 주소
const ADDR: &'static str = "localhost:8000";
/// 마크다운 문서가 담긴 주소
const DOCS_DIR: &'static str = "docs";

/// Entry point
fn main() {
    //
    //      User sends request
    //               ⇩
    //                                '/public' 디렉토리에서 해당 파일이 있는지 먼저 찾아본다.
    //    try static file serving     있을경우 이를 전송하고, 없을경우 아래의 main handler로
    //    (not in production mode)    넘어간다. production mode로 실행될 경우, 이 동작이 없어지므로
    //                                nginx나 apache의 정적파일서빙 기능을 써야한다.
    //               ⇩
    //        "main handlers"         index, page, all_docs 등의 함수로 요청을 처리한다
    //               ⇩
    //       404 page handler         위의 두개가 모두 실패하였을경우 404페이지를 렌더링한다
    //               ⇩
    //     handlebar templating
    //

    let mut c = Chain::new(router! {
        get "/" => index,
        get "/pages/:name" => page,
        get "/pages/_pages" => all_docs,
    });

    // Static file serving (not in production mode)
    if !is_production() {
        c.link_around(move |main: Box<Handler>| -> Box<Handler> {
            Box::new(move |req: &mut Request| -> IronResult<Response> {
                Static::new("public/").handle(req)
                    .or_else(|_| main.handle(req))
            })
        });
    }
    // 404 page handler
    c.link_after(catch(|mut err: IronError| {
        if err.response.body.is_some() { return Err(err); }
        if err.response.status != Some(status::NotFound) { return Err(err); }

        // TODO: 좀더 내용 채우기
        let mut data = BTreeMap::new();
        data.insert("content", r#"

404

This is not the web page you are looking for.

        "#);
        err.response.set_mut(Template::new("default", data));
        Err(err)
    }));
    // Handlebar templating
    c.link_after({
        let mut hbr = HandlebarsEngine::new();
        hbr.add(Box::new(DirectorySource::new("templates", ".hbs")));
        if let Err(r) = hbr.reload() {
            use std::error::Error;
            panic!("{}", r.description());
        }
        hbr
    });

    println!("\nServer running at \x1b[33mhttp://{}\x1b[0m\n", ADDR);
    Iron::new(c).http(ADDR).unwrap();
}

/// Root page handler
fn index(_: &mut Request) -> IronResult<Response> {
    read_docs("Home")
}

/// Wiki page handler
fn page(req: &mut Request) -> IronResult<Response> {
    use router::Router;

    // Parse URL
    let name = req.extensions.get::<Router>().unwrap().find("name").unwrap_or("Home");
    read_docs(name)
}

/// "All documents" page handler
fn all_docs(_: &mut Request) -> IronResult<Response> {
    use std::fs::read_dir;

    let mut paths: Vec<_> = itry!(read_dir(DOCS_DIR), status::NotFound)
        .filter_map(|f| f.ok())
        .map(|f| f.path())
        .filter(|p| p.is_file())
        .filter(|p| p.as_os_str().to_str()
            .map(|s| s.ends_with(".md"))
            .unwrap_or(false))
        .collect();
    paths.sort();

    let pages = paths.iter()
        .filter_map(|p| p.file_stem())
        .filter_map(|stem| stem.to_str());

    // TODO: 러스트로 이짓하지 말고 Handlebar로 대체
    let mut html = "
".to_string();
    for page in pages {
        use std::fmt::Write;
        write!(&mut html, r#"
{0}
"#, page).unwrap();
    }
    html.push_str("
");

    // Fill in to the template
    let mut data = BTreeMap::new();
    data.insert("content", html);
    Ok(Response::with((status::Ok, Template::new("default", data))))
}

/// `name`을 인자로 받아, `docs/<name>.md` 파일을 렌더링하여 `IronResult<Response>`로 반환합니다.
fn read_docs(name: &str) -> IronResult<Response> {
    use std::fs::File;
    use std::io::Read;
    use cmark::Parser;
    use cmark::html::push_html;

    // Read file
    let path = format!("{}/{}.md", DOCS_DIR, name);
    let mut file = itry!(File::open(&path), status::NotFound);
    let mut md = String::new();
    itry!(file.read_to_string(&mut md), status::ServiceUnavailable);

    // Parse markdown
    let parser = Parser::new(&md);
    let mut html = String::new();
    push_html(&mut html, parser);

    // Fill in to the template
    let mut data = BTreeMap::new();
    data.insert("content", html);
    Ok(Response::with((status::Ok, Template::new("default", data))))
}

/// `RUST_KR` 환경변수가 `"production"`일경우 true, 그 외의경우 false를 반환한다.
fn is_production() -> bool {
    use std::env;

    env::var("RUST_KR")
        .map(|s| s == "production")
        .unwrap_or(false)
}

/// Helper struct for handle 404 page of rust-kr
struct RustkrHandler<F> { handler: F }
/// Helper function for handle 404 page of rust-kr
fn catch<F>(handler: F) -> RustkrHandler<F> { RustkrHandler { handler: handler } }
impl<F> AfterMiddleware for RustkrHandler<F>
    where F: Send + Sync + 'static + Fn(IronError) -> IronResult<Response> {
    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
        (self.handler)(err)
    }
}
<commit_msg>현재 어떤 모드로 실행되고있는지 콘솔에 출력하도록 수정<commit_after>//! [한국 러스트 사용자 그룹 홈페이지][rust-kr] 소스코드
//! --------
//!
//! ### 사용법
//! ```bash
//! git clone https://github.com/rust-kr/rust-kr.org.wiki.git docs
//! cargo run
//! # 웹 브라우저에서 http://localhost:8000 를 열어보세요
//! ```
//!
//! [rust-kr]: http://rust-kr.org

// 한국 러스트 사용자 그룹 홈페이지
// Copyright (C) 2016  Hyeon Kim
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#[macro_use(itry)] extern crate iron;
#[macro_use(router)] extern crate router;
extern crate staticfile;
extern crate handlebars_iron as hbs;
extern crate pulldown_cmark as cmark;

use std::collections::BTreeMap;
use std::fmt;
use iron::prelude::*;
use iron::status;
use iron::middleware::{Handler, AfterMiddleware};
use staticfile::Static;
use hbs::{Template, HandlebarsEngine, DirectorySource};

//
// Configs
//
/// 서버가 소켓을 열 주소
const ADDR: &'static str = "localhost:8000";
/// 마크다운 문서가 담긴 주소
const DOCS_DIR: &'static str = "docs";

/// Entry point
fn main() {
    let mode = get_mode();

    //
    //      User sends request
    //               ⇩
    //                                '/public' 디렉토리에서 해당 파일이 있는지 먼저 찾아본다.
    //    try static file serving     있을경우 이를 전송하고, 없을경우 아래의 main handler로
    //   (only in development mode)   넘어간다. production mode로 실행될 경우, 이 동작이 없어지므로
    //                                nginx나 apache의 정적파일서빙 기능을 써야한다.
    //               ⇩
    //        "main handlers"         index, page, all_docs 등의 함수로 요청을 처리한다
    //               ⇩
    //       404 page handler         위의 두개가 모두 실패하였을경우 404페이지를 렌더링한다
    //               ⇩
    //     handlebar templating
    //

    let mut c = Chain::new(router! {
        get "/" => index,
        get "/pages/:name" => page,
        get "/pages/_pages" => all_docs,
    });

    // Static file serving (only in development mode)
    if mode == Mode::Development {
        c.link_around(move |main: Box<Handler>| -> Box<Handler> {
            Box::new(move |req: &mut Request| -> IronResult<Response> {
                Static::new("public/").handle(req)
                    .or_else(|_| main.handle(req))
            })
        });
    }
    // 404 page handler
    c.link_after(catch(|mut err: IronError| {
        if err.response.body.is_some() { return Err(err); }
        if err.response.status != Some(status::NotFound) { return Err(err); }

        // TODO: 좀더 내용 채우기
        let mut data = BTreeMap::new();
        data.insert("content", r#"

404

This is not the web page you are looking for.

        "#);
        err.response.set_mut(Template::new("default", data));
        Err(err)
    }));
    // Handlebar templating
    c.link_after({
        let mut hbr = HandlebarsEngine::new();
        hbr.add(Box::new(DirectorySource::new("templates", ".hbs")));
        if let Err(r) = hbr.reload() {
            use std::error::Error;
            panic!("{}", r.description());
        }
        hbr
    });

    println!("\nServer running at \x1b[32mhttp://{}\x1b[0m in \x1b[33m{}\x1b[0m mode\n", ADDR, mode);
    Iron::new(c).http(ADDR).unwrap();
}

/// Root page handler
fn index(_: &mut Request) -> IronResult<Response> {
    read_docs("Home")
}

/// Wiki page handler
fn page(req: &mut Request) -> IronResult<Response> {
    use router::Router;

    // Parse URL
    let name = req.extensions.get::<Router>().unwrap().find("name").unwrap_or("Home");
    read_docs(name)
}

/// "All documents" page handler
fn all_docs(_: &mut Request) -> IronResult<Response> {
    use std::fs::read_dir;

    let mut paths: Vec<_> = itry!(read_dir(DOCS_DIR), status::NotFound)
        .filter_map(|f| f.ok())
        .map(|f| f.path())
        .filter(|p| p.is_file())
        .filter(|p| p.as_os_str().to_str()
            .map(|s| s.ends_with(".md"))
            .unwrap_or(false))
        .collect();
    paths.sort();

    let pages = paths.iter()
        .filter_map(|p| p.file_stem())
        .filter_map(|stem| stem.to_str());

    // TODO: 러스트로 이짓하지 말고 Handlebar로 대체
    let mut html = "
".to_string();
    for page in pages {
        use std::fmt::Write;
        write!(&mut html, r#"
{0}
"#, page).unwrap();
    }
    html.push_str("
");

    // Fill in to the template
    let mut data = BTreeMap::new();
    data.insert("content", html);
    Ok(Response::with((status::Ok, Template::new("default", data))))
}

/// `name`을 인자로 받아, `docs/<name>.md` 파일을 렌더링하여 `IronResult<Response>`로 반환합니다.
fn read_docs(name: &str) -> IronResult<Response> {
    use std::fs::File;
    use std::io::Read;
    use cmark::Parser;
    use cmark::html::push_html;

    // Read file
    let path = format!("{}/{}.md", DOCS_DIR, name);
    let mut file = itry!(File::open(&path), status::NotFound);
    let mut md = String::new();
    itry!(file.read_to_string(&mut md), status::ServiceUnavailable);

    // Parse markdown
    let parser = Parser::new(&md);
    let mut html = String::new();
    push_html(&mut html, parser);

    // Fill in to the template
    let mut data = BTreeMap::new();
    data.insert("content", html);
    Ok(Response::with((status::Ok, Template::new("default", data))))
}

/// 현재 프로그램이 개발모드로 실행되는지, 실서비스 모드로 실행되는지 여부를 저장하는 타입.
///
/// `get_mode()` 함수로 값을 얻어올 수 있다.
#[derive(PartialEq)]
enum Mode { Production, Development }

impl fmt::Display for Mode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(match *self {
            Mode::Production => "production",
            Mode::Development => "development",
        })
    }
}

/// `RUST_KR` 환경변수가 `"production"`일경우 Mode::Production, 그 외의경우 Mode::Development를 반환한다.
fn get_mode() -> Mode {
    use std::env;
    use Mode::*;

    env::var("RUST_KR")
        .map(|s| if s == "production" { Production } else { Development })
        .unwrap_or(Development)
}

/// Helper struct for handle 404 page of rust-kr
struct RustkrHandler<F> { handler: F }
/// Helper function for handle 404 page of rust-kr
fn catch<F>(handler: F) -> RustkrHandler<F> { RustkrHandler { handler: handler } }
impl<F> AfterMiddleware for RustkrHandler<F>
    where F: Send + Sync + 'static + Fn(IronError) -> IronResult<Response> {
    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
        (self.handler)(err)
    }
}
<|endoftext|>


<commit_before>// UDP stuff adapted from http://illegalargumentexception.blogspot.co.uk/2015/05/rust-send-and-receive-on-localhost-with.html
use std::net;
#[macro_use]
extern crate clap;
use clap::{Arg, App};

fn socket(listen_on: net::SocketAddr) -> net::UdpSocket {
    let attempt = net::UdpSocket::bind(listen_on);
    let socket;
    match attempt {
        Ok(sock) => {
            socket = sock;
        }
        Err(err) => panic!("Could not bind: {}", err),
    }
    socket
}

pub fn send_message(send_addr: net::SocketAddr, target: net::SocketAddr, data: Vec<u8>) {
    let socket = socket(send_addr);
    let _ = socket.send_to(&data, target);
    drop(socket);
}

fn main() {
    let command_vals = ["white", "red", "orange", "yellow", "green", "cyan", "blue", "purple",
                        "black", "?", "!", "quit"];
    let matches = App::new("rust_anybar")
                      .version(&crate_version!()[..])
                      .author("Stephan Hügel <urschrei@gmail.com>")
                      .about("A Rust command-line client for Anybar")
                      .args_from_usage("-p --port=[PORT] 'Set destination UDP port. Input must \
                                        be 0 – 65535, and defaults to 17388")
                      .arg(Arg::with_name("COMMAND")
                               .help("The command you wish to send to Anybar")
                               .index(1)
                               .possible_values(&command_vals)
                               .required(true))
                      .get_matches();
    let numeric_port = value_t!(matches.value_of("PORT"), u16).unwrap_or(1738);
    let to_send = matches.value_of("COMMAND").unwrap().to_owned().to_lowercase();
    // blam our control message into a vector
    let mut message: Vec<u8> = Vec::new();
    message.extend(to_send.as_bytes()
                          .iter()
                          .cloned());
    // bind to the correct UDP port
    let ip = net::Ipv4Addr::new(127, 0, 0, 1);
    let listen_addr = net::SocketAddrV4::new(ip, numeric_port);
    let send_addr = net::SocketAddrV4::new(ip, 0);
    // and send our message
    send_message(net::SocketAddr::V4(send_addr),
                 net::SocketAddr::V4(listen_addr),
                 message);
}
<commit_msg>Rustfmt update<commit_after>// UDP stuff adapted from http://illegalargumentexception.blogspot.co.uk/2015/05/rust-send-and-receive-on-localhost-with.html
use std::net;
#[macro_use]
extern crate clap;
use clap::{Arg, App};

fn socket(listen_on: net::SocketAddr) -> net::UdpSocket {
    let attempt = net::UdpSocket::bind(listen_on);
    let socket;
    match attempt {
        Ok(sock) => {
            socket = sock;
        }
        Err(err) => panic!("Could not bind: {}", err),
    }
    socket
}

pub fn send_message(send_addr: net::SocketAddr, target: net::SocketAddr, data: Vec<u8>) {
    let socket = socket(send_addr);
    let _ = socket.send_to(&data, target);
    drop(socket);
}

fn main() {
    let command_vals = ["white", "red", "orange", "yellow", "green", "cyan", "blue", "purple",
                        "black", "?", "!", "quit"];
    let matches = App::new("rust_anybar")
        .version(&crate_version!()[..])
        .author("Stephan Hügel <urschrei@gmail.com>")
        .about("A Rust command-line client for Anybar")
        .args_from_usage("-p --port=[PORT] 'Set destination UDP port. Input must be 0 – 65535, \
                          and defaults to 17388")
        .arg(Arg::with_name("COMMAND")
            .help("The command you wish to send to Anybar")
            .index(1)
            .possible_values(&command_vals)
            .required(true))
        .get_matches();
    let numeric_port = value_t!(matches.value_of("PORT"), u16).unwrap_or(1738);
    let to_send = matches.value_of("COMMAND").unwrap().to_owned().to_lowercase();
    // blam our control message into a vector
    let mut message: Vec<u8> = Vec::new();
    message.extend(to_send.as_bytes()
        .iter()
        .cloned());
    // bind to the correct UDP port
    let ip = net::Ipv4Addr::new(127, 0, 0, 1);
    let listen_addr = net::SocketAddrV4::new(ip, numeric_port);
    let send_addr = net::SocketAddrV4::new(ip, 0);
    // and send our message
    send_message(net::SocketAddr::V4(send_addr),
                 net::SocketAddr::V4(listen_addr),
                 message);
}
<|endoftext|>