<commit_before>use encoding_rs::Encoding;
use html5ever::rcdom::RcDom;
use reqwest::blocking::Client;
use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
use std::collections::HashMap;
use std::fs;
use std::io::{self, prelude::*, Error, Write};
use std::path::Path;
use std::process;
use std::time::Duration;
use url::Url;

use monolith::html::{
    add_favicon, create_metadata_tag, get_base_url, get_charset, has_favicon, html_to_dom,
    serialize_document, set_base_url, set_charset, walk_and_embed_assets,
};
use monolith::opts::Options;
use monolith::url::{create_data_url, resolve_url};
use monolith::utils::retrieve_asset;

mod macros;

enum Output {
    Stdout(io::Stdout),
    File(fs::File),
}

impl Output {
    fn new(file_path: &str) -> Result<Output, Error> {
        if file_path.is_empty() || file_path.eq("-") {
            Ok(Output::Stdout(io::stdout()))
        } else {
            Ok(Output::File(fs::File::create(file_path)?))
        }
    }

    fn write(&mut self, bytes: &Vec<u8>) -> Result<(), Error> {
        match self {
            Output::Stdout(stdout) => {
                stdout.write_all(bytes)?;
                // Ensure newline at end of output
                if bytes.last() != Some(&b"\n"[0]) {
                    stdout.write(b"\n")?;
                }
                stdout.flush()
            }
            Output::File(file) => {
                file.write_all(bytes)?;
                // Ensure newline at end of output
                if bytes.last() != Some(&b"\n"[0]) {
                    file.write(b"\n")?;
                }
                file.flush()
            }
        }
    }
}

pub fn read_stdin() -> Vec<u8> {
    let mut buffer: Vec<u8> = vec![];

    match io::stdin().lock().read_to_end(&mut buffer) {
        Ok(_) => buffer,
        Err(_) => buffer,
    }
}

fn main() {
    let options = Options::from_args();
    let mut target: String = str!(&options.target.clone());

    // Check if target was provided
    if target.len() == 0 {
        if !options.silent {
            eprintln!("No target specified");
        }
        process::exit(1);
    }

    // Check if custom charset is valid
    if let Some(custom_charset) = options.charset.clone() {
        if !Encoding::for_label_no_replacement(custom_charset.as_bytes()).is_some() {
            eprintln!("Unknown encoding: {}", &custom_charset);
            process::exit(1);
        }
    }

    let target_url: Url;
    let mut base_url: Url;
    let mut use_stdin: bool = false;

    // Determine exact target URL
    if target.clone() == "-" {
        // Read from pipe (stdin)
        use_stdin = true;
        // Set default target URL to an empty data URL; the user can set it via --base-url
        target_url = Url::parse("data:text/html,").unwrap();
    } else {
        match Url::parse(&target.clone()) {
            Ok(parsed_url) => {
                if parsed_url.scheme() == "data"
                    || parsed_url.scheme() == "file"
                    || (parsed_url.scheme() == "http" || parsed_url.scheme() == "https")
                {
                    target_url = parsed_url;
                } else {
                    if !options.silent {
                        eprintln!("Unsupported target URL type: {}", &parsed_url.scheme());
                    }
                    process::exit(1);
                }
            }
            Err(_err) => {
                // Failed to parse given base URL,
                // perhaps it's a filesystem path?
                let path: &Path = Path::new(&target);

                if path.exists() {
                    if path.is_file() {
                        match Url::from_file_path(fs::canonicalize(&path).unwrap()) {
                            Ok(file_url) => {
                                target_url = file_url;
                            }
                            Err(_err) => {
                                if !options.silent {
                                    eprintln!(
                                        "Could not generate file URL out of given path: {}",
                                        "err"
                                    );
                                }
                                process::exit(1);
                            }
                        }
                    } else {
                        if !options.silent {
                            eprintln!("Local target is not a file: {}", &options.target);
                        }
                        process::exit(1);
                    }
                } else {
                    // Last chance, now we do what browsers do:
                    // prepend "http://" and hope it points to a website
                    target.insert_str(0, "http://");
                    target_url = Url::parse(&target).unwrap();
                }
            }
        }
    }

    // Initialize client
    let mut cache = HashMap::new();
    let mut header_map = HeaderMap::new();
    if let Some(user_agent) = &options.user_agent {
        header_map.insert(
            USER_AGENT,
            HeaderValue::from_str(&user_agent).expect("Invalid User-Agent header specified"),
        );
    }
    let timeout: u64 = if options.timeout > 0 {
        options.timeout
    } else {
        std::u64::MAX / 4 // This is pretty close to infinity
    };
    let client = Client::builder()
        .timeout(Duration::from_secs(timeout))
        .danger_accept_invalid_certs(options.insecure)
        .default_headers(header_map)
        .build()
        .expect("Failed to initialize HTTP client");

    // At this stage we assume that the base URL is the same as the target URL
    base_url = target_url.clone();

    let data: Vec<u8>;
    let mut document_encoding: String = str!();
    let mut dom: RcDom;

    // Retrieve target document
    if use_stdin {
        data = read_stdin();
    } else if target_url.scheme() == "file"
        || (target_url.scheme() == "http" || target_url.scheme() == "https")
        || target_url.scheme() == "data"
    {
        match retrieve_asset(&mut cache, &client, &target_url, &target_url, &options, 0) {
            Ok((retrieved_data, final_url, media_type, charset)) => {
                // Make sure the media type is text/html
                if !media_type.eq_ignore_ascii_case("text/html") {
                    if !options.silent {
                        eprintln!("Unsupported document media type");
                    }
                    process::exit(1);
                }

                if options.base_url.clone().unwrap_or(str!()).is_empty() {
                    base_url = final_url;
                }

                data = retrieved_data;
                document_encoding = charset;
            }
            Err(_) => {
                if !options.silent {
                    eprintln!("Could not retrieve target document");
                }
                process::exit(1);
            }
        }
    } else {
        process::exit(1);
    }

    // Initial parse
    dom = html_to_dom(&data, document_encoding.clone());

    // TODO: investigate if charset from filesystem/data URL/HTTP headers
    //       has power over what's specified in HTML

    // Attempt to determine document's charset
    if let Some(charset) = get_charset(&dom.document) {
        if !charset.is_empty() {
            // Check if the charset specified inside HTML is valid
            if let Some(encoding) = Encoding::for_label(charset.as_bytes()) {
                // No point in parsing HTML again with the same encoding as before
                if encoding.name() != "UTF-8" {
                    document_encoding = charset;
                    dom = html_to_dom(&data, document_encoding.clone());
                }
            }
        }
    }

    // Use custom base URL if specified, read and use what's in the DOM otherwise
    let custom_base_url: String = options.base_url.clone().unwrap_or(str!());
    if custom_base_url.is_empty() {
        // No custom base URL is specified,
        // try to see if the document has BASE tag
        if let Some(existing_base_url) = get_base_url(&dom.document) {
            base_url = resolve_url(&target_url, &existing_base_url);
        }
    } else {
        // Custom base URL provided
        match Url::parse(&custom_base_url) {
            Ok(parsed_url) => {
                if parsed_url.scheme() == "file" {
                    // File base URLs can only work with
                    // documents saved from filesystem
                    if target_url.scheme() == "file" {
                        base_url = parsed_url;
                    }
                } else {
                    base_url = parsed_url;
                }
            }
            Err(_) => {
                // Failed to parse given base URL,
                // perhaps it's a filesystem path?
                if target_url.scheme() == "file" {
                    // Relative paths could work for documents saved from filesystem
                    let path: &Path = Path::new(&custom_base_url);
                    if path.exists() {
                        match Url::from_file_path(fs::canonicalize(&path).unwrap()) {
                            Ok(file_url) => {
                                base_url = file_url;
                            }
                            Err(_) => {
                                if !options.silent {
                                    eprintln!(
                                        "Could not map given path to base URL: {}",
                                        custom_base_url
                                    );
                                }
                                process::exit(1);
                            }
                        }
                    }
                }
            }
        }
    }

    // Traverse through the document and embed remote assets
    walk_and_embed_assets(&mut cache, &client, &base_url, &dom.document, &options, 0);

    // Update or add new BASE element to reroute network requests and hash-links
    if let Some(new_base_url) = options.base_url.clone() {
        dom = set_base_url(&dom.document, new_base_url);
    }

    // Request and embed /favicon.ico (unless it's already linked in the document)
    if !options.no_images
        && (target_url.scheme() == "http" || target_url.scheme() == "https")
        && !has_favicon(&dom.document)
    {
        let favicon_ico_url: Url = resolve_url(&base_url, "/favicon.ico");

        match retrieve_asset(
            &mut cache,
            &client,
            &target_url,
            &favicon_ico_url,
            &options,
            0,
        ) {
            Ok((data, final_url, media_type, _charset)) => {
                // TODO: use charset
                let favicon_data_url: Url = create_data_url(&media_type, &data, &final_url);
                dom = add_favicon(&dom.document, favicon_data_url.to_string());
            }
            Err(_) => {
                // Failed to retrieve /favicon.ico
            }
        }
    }

    // Save using specified charset, if given
    if let Some(custom_charset) = options.charset.clone() {
        document_encoding = custom_charset;
        dom = set_charset(dom, document_encoding.clone());
    }

    // Serialize DOM tree
    let mut result: Vec<u8> = serialize_document(dom, document_encoding, &options);

    // Add metadata tag
    if !options.no_metadata {
        let mut metadata_comment: String = create_metadata_tag(&target_url);
        metadata_comment += "\n";
        result.splice(0..0, metadata_comment.as_bytes().to_vec());
    }

    // Define output
    let mut output = Output::new(&options.output).expect("Could not prepare output");

    // Write result into stdout or file
    output.write(&result).expect("Could not write HTML output");
}
<commit_msg>improve validation of charset found in HTML, use genuinely infinite timeout<commit_after>use encoding_rs::Encoding;
use html5ever::rcdom::RcDom;
use reqwest::blocking::Client;
use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
use std::collections::HashMap;
use std::fs;
use std::io::{self, prelude::*, Error, Write};
use std::path::Path;
use std::process;
use std::time::Duration;
use url::Url;

use monolith::html::{
    add_favicon, create_metadata_tag, get_base_url, get_charset, has_favicon, html_to_dom,
    serialize_document, set_base_url, set_charset, walk_and_embed_assets,
};
use monolith::opts::Options;
use monolith::url::{create_data_url, resolve_url};
use monolith::utils::retrieve_asset;

mod macros;

enum Output {
    Stdout(io::Stdout),
    File(fs::File),
}

impl Output {
    fn new(file_path: &str) -> Result<Output, Error> {
        if file_path.is_empty() || file_path.eq("-") {
            Ok(Output::Stdout(io::stdout()))
        } else {
            Ok(Output::File(fs::File::create(file_path)?))
        }
    }

    fn write(&mut self, bytes: &Vec<u8>) -> Result<(), Error> {
        match self {
            Output::Stdout(stdout) => {
                stdout.write_all(bytes)?;
                // Ensure newline at end of output
                if bytes.last() != Some(&b"\n"[0]) {
                    stdout.write(b"\n")?;
                }
                stdout.flush()
            }
            Output::File(file) => {
                file.write_all(bytes)?;
                // Ensure newline at end of output
                if bytes.last() != Some(&b"\n"[0]) {
                    file.write(b"\n")?;
                }
                file.flush()
            }
        }
    }
}

pub fn read_stdin() -> Vec<u8> {
    let mut buffer: Vec<u8> = vec![];

    match io::stdin().lock().read_to_end(&mut buffer) {
        Ok(_) => buffer,
        Err(_) => buffer,
    }
}

fn main() {
    let options = Options::from_args();
    let mut target: String = str!(&options.target.clone());

    // Check if target was provided
    if target.len() == 0 {
        if !options.silent {
            eprintln!("No target specified");
        }
        process::exit(1);
    }

    // Check if custom charset is valid
    if let Some(custom_charset) = options.charset.clone() {
        if !Encoding::for_label_no_replacement(custom_charset.as_bytes()).is_some() {
            eprintln!("Unknown encoding: {}", &custom_charset);
            process::exit(1);
        }
    }

    let target_url: Url;
    let mut use_stdin: bool = false;

    // Determine exact target URL
    if target.clone() == "-" {
        // Read from pipe (stdin)
        use_stdin = true;
        // Set default target URL to an empty data URL; the user can set it via --base-url
        target_url = Url::parse("data:text/html,").unwrap();
    } else {
        match Url::parse(&target.clone()) {
            Ok(parsed_url) => {
                if parsed_url.scheme() == "data"
                    || parsed_url.scheme() == "file"
                    || (parsed_url.scheme() == "http" || parsed_url.scheme() == "https")
                {
                    target_url = parsed_url;
                } else {
                    if !options.silent {
                        eprintln!("Unsupported target URL type: {}", &parsed_url.scheme());
                    }
                    process::exit(1);
                }
            }
            Err(_err) => {
                // Failed to parse given base URL,
                // perhaps it's a filesystem path?
                let path: &Path = Path::new(&target);

                if path.exists() {
                    if path.is_file() {
                        match Url::from_file_path(fs::canonicalize(&path).unwrap()) {
                            Ok(file_url) => {
                                target_url = file_url;
                            }
                            Err(_err) => {
                                if !options.silent {
                                    eprintln!(
                                        "Could not generate file URL out of given path: {}",
                                        "err"
                                    );
                                }
                                process::exit(1);
                            }
                        }
                    } else {
                        if !options.silent {
                            eprintln!("Local target is not a file: {}", &options.target);
                        }
                        process::exit(1);
                    }
                } else {
                    // Last chance, now we do what browsers do:
                    // prepend "http://" and hope it points to a website
                    target.insert_str(0, "http://");
                    target_url = Url::parse(&target).unwrap();
                }
            }
        }
    }

    // Initialize client
    let mut cache = HashMap::new();
    let mut header_map = HeaderMap::new();
    if let Some(user_agent) = &options.user_agent {
        header_map.insert(
            USER_AGENT,
            HeaderValue::from_str(&user_agent).expect("Invalid User-Agent header specified"),
        );
    }
    let client = if options.timeout > 0 {
        Client::builder().timeout(Duration::from_secs(options.timeout))
    } else {
        // No timeout is default
        Client::builder()
    }
    .danger_accept_invalid_certs(options.insecure)
    .default_headers(header_map)
    .build()
    .expect("Failed to initialize HTTP client");

    // At first we assume that base URL is the same as target URL
    let mut base_url: Url = target_url.clone();

    let data: Vec<u8>;
    let mut document_encoding: String = str!();
    let mut dom: RcDom;

    // Retrieve target document
    if use_stdin {
        data = read_stdin();
    } else if target_url.scheme() == "file"
        || (target_url.scheme() == "http" || target_url.scheme() == "https")
        || target_url.scheme() == "data"
    {
        match retrieve_asset(&mut cache, &client, &target_url, &target_url, &options, 0) {
            Ok((retrieved_data, final_url, media_type, charset)) => {
                // Make sure the media type is text/html
                if !media_type.eq_ignore_ascii_case("text/html") {
                    if !options.silent {
                        eprintln!("Unsupported document media type");
                    }
                    process::exit(1);
                }

                if options.base_url.clone().unwrap_or(str!()).is_empty() {
                    base_url = final_url;
                }

                data = retrieved_data;
                document_encoding = charset;
            }
            Err(_) => {
                if !options.silent {
                    eprintln!("Could not retrieve target document");
                }
                process::exit(1);
            }
        }
    } else {
        process::exit(1);
    }

    // Initial parse
    dom = html_to_dom(&data, document_encoding.clone());

    // TODO: investigate if charset from filesystem/data URL/HTTP headers
    //       has say over what's specified in HTML

    // Attempt to determine document's charset
    if let Some(html_charset) = get_charset(&dom.document) {
        if !html_charset.is_empty() {
            // Check if the charset specified inside HTML is valid
            if let Some(encoding) = Encoding::for_label_no_replacement(html_charset.as_bytes()) {
                // No point in parsing HTML again with the same encoding as before
                if encoding.name() != "UTF-8" {
                    document_encoding = html_charset;
                    dom = html_to_dom(&data, document_encoding.clone());
                }
            }
        }
    }

    // Use custom base URL if specified, read and use what's in the DOM otherwise
    let custom_base_url: String = options.base_url.clone().unwrap_or(str!());
    if custom_base_url.is_empty() {
        // No custom base URL is specified
        // Try to see if document has BASE element
        if let Some(existing_base_url) = get_base_url(&dom.document) {
            base_url = resolve_url(&target_url, &existing_base_url);
        }
    } else {
        // Custom base URL provided
        match Url::parse(&custom_base_url) {
            Ok(parsed_url) => {
                if parsed_url.scheme() == "file" {
                    // File base URLs can only work with
                    // documents saved from filesystem
                    if target_url.scheme() == "file" {
                        base_url = parsed_url;
                    }
                } else {
                    base_url = parsed_url;
                }
            }
            Err(_) => {
                // Failed to parse given base URL, perhaps it's a filesystem path?
                if target_url.scheme() == "file" {
                    // Relative paths could work for documents saved from filesystem
                    let path: &Path = Path::new(&custom_base_url);
                    if path.exists() {
                        match Url::from_file_path(fs::canonicalize(&path).unwrap()) {
                            Ok(file_url) => {
                                base_url = file_url;
                            }
                            Err(_) => {
                                if !options.silent {
                                    eprintln!(
                                        "Could not map given path to base URL: {}",
                                        custom_base_url
                                    );
                                }
                                process::exit(1);
                            }
                        }
                    }
                }
            }
        }
    }

    // Traverse through the document and embed remote assets
    walk_and_embed_assets(&mut cache, &client, &base_url, &dom.document, &options, 0);

    // Update or add new BASE element to reroute network requests and hash-links
    if let Some(new_base_url) = options.base_url.clone() {
        dom = set_base_url(&dom.document, new_base_url);
    }

    // Request and embed /favicon.ico (unless it's already linked in the document)
    if !options.no_images
        && (target_url.scheme() == "http" || target_url.scheme() == "https")
        && !has_favicon(&dom.document)
    {
        let favicon_ico_url: Url = resolve_url(&base_url, "/favicon.ico");

        match retrieve_asset(
            &mut cache,
            &client,
            &target_url,
            &favicon_ico_url,
            &options,
            0,
        ) {
            Ok((data, final_url, media_type, _charset)) => {
                // TODO: use charset
                let favicon_data_url: Url = create_data_url(&media_type, &data, &final_url);
                dom = add_favicon(&dom.document, favicon_data_url.to_string());
            }
            Err(_) => {
                // Failed to retrieve /favicon.ico
            }
        }
    }

    // Save using specified charset, if given
    if let Some(custom_charset) = options.charset.clone() {
        document_encoding = custom_charset;
        dom = set_charset(dom, document_encoding.clone());
    }

    // Serialize DOM tree
    let mut result: Vec<u8> = serialize_document(dom, document_encoding, &options);

    // Prepend metadata comment tag
    if !options.no_metadata {
        let mut metadata_comment: String = create_metadata_tag(&target_url);
        metadata_comment += "\n";
        result.splice(0..0, metadata_comment.as_bytes().to_vec());
    }

    // Define output
    let mut output = Output::new(&options.output).expect("Could not prepare output");

    // Write result into stdout or file
    output.write(&result).expect("Could not write HTML output");
}
<|endoftext|>


<commit_before>extern crate monorail;
extern crate term;

use monorail::action::Move;
use monorail::board::Board;
use monorail::player::Player;
use std::env;
use std::io;

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
enum GameResult {
    PlaceholderAlpha,
    JunSeokWin,
    YeonSeungWin,
    PlaceholderBeta,
}

impl GameResult {
    fn win_for(&self, p: Player) -> bool {
        match (*self, p) {
            (GameResult::JunSeokWin, Player::JunSeok) => true,
            (GameResult::JunSeokWin, _) => false,
            (GameResult::YeonSeungWin, Player::YeonSeung) => true,
            (GameResult::YeonSeungWin, _) => false,
            (GameResult::PlaceholderAlpha, _) => panic!("Can't evaluate winningness of alpha"),
            (GameResult::PlaceholderBeta, _) => panic!("Can't evaluate winningness of beta"),
        }
    }
}

fn minimax_alpha_beta(player: Player, board: &mut Board, initial_alpha: GameResult, initial_beta: GameResult) -> (GameResult, Option<Move>) {
    let moves = board.legal_moves();
    // There are no more moves, which means my opponent completed the railroad.
    // So I lose.
    if moves.is_empty() {
        return match player {
            Player::YeonSeung => (GameResult::JunSeokWin, None),
            Player::JunSeok => (GameResult::YeonSeungWin, None),
        }
    }
    let mut best = match player {
        Player::YeonSeung => initial_alpha,
        Player::JunSeok => initial_beta,
    };
    let mut alpha = initial_alpha;
    let mut beta = initial_beta;
    let mut best_move = None;

    for possible_move in moves.iter() {
        board.make_move(*possible_move);
        let (reply, _) = minimax_alpha_beta(player.opponent(), board, alpha, beta);
        board.undo_move(*possible_move);

        match player {
            Player::YeonSeung => {
                if reply > best {
                    best = reply;
                    alpha = reply;
                    best_move = Some(*possible_move);
                }
                if best >= GameResult::YeonSeungWin {
                    return (best, best_move);
                }
            },
            Player::JunSeok => {
                if reply < best {
                    best = reply;
                    beta = reply;
                    best_move = Some(*possible_move);
                }
                if best <= GameResult::JunSeokWin {
                    return (best, best_move);
                }
            },
        }

        if alpha >= beta {
            return (best, best_move);
        }
    }

    (best, best_move)
}

fn print_result(result: GameResult, color: term::color::Color, colorize: bool) {
    if colorize {
        let mut t = term::stdout().unwrap();
        t.fg(color).unwrap();
        t.attr(term::Attr::Bold).unwrap();
        writeln!(t, "{:?}", result).unwrap();
        t.reset().unwrap();
    } else {
        println!("{:?}", result);
    }
}

fn print_all_responses(player: Player, starting_board: &mut Board, colorize: bool) {
    for legal_move in starting_board.legal_moves().iter() {
        print!("If {:?} does: {}, ", player, legal_move);
        starting_board.make_move(*legal_move);
        let (result, best_move) = minimax_alpha_beta(player.opponent(), starting_board, GameResult::PlaceholderAlpha, GameResult::PlaceholderBeta);
        if result.win_for(player) {
            print_result(result, term::color::BLUE, colorize);
            println!("{}", starting_board);
        } else if let Some(opponent_move) = best_move {
            print!("{:?} does: {}, ", player.opponent(), opponent_move);
            print_result(result, term::color::RED, colorize);
            starting_board.make_move(opponent_move);
            println!("{}", starting_board);
            starting_board.undo_move(opponent_move);
        } else {
            panic!("no move?");
        }
        starting_board.undo_move(*legal_move);
    }
}

fn print_best_move(player: Player, starting_board: &mut Board) {
    let (result, best_move) = minimax_alpha_beta(player, starting_board, GameResult::PlaceholderAlpha, GameResult::PlaceholderBeta);
    println!("{:?}", result);
    match best_move {
        Some(x) => {
            println!("{}", x);
            starting_board.make_move(x);
            println!("{}", starting_board);
            starting_board.undo_move(x);
        },
        None => println!("No move"),
    }
}

fn main() {
    let mut starting_board = Board::new(
        [
            [false,  true,  true,  true, false],
            [false, false, false,  true, false],
            [false, false, false,  true, false],
            [false, false, false, false, false],
        ],
        None,
    );
    let starting_player = Player::YeonSeung;

    let mut all_responses = false;
    let mut best_move = false;
    let mut legal_moves = false;
    let mut colorize = false;

    for argument in env::args() {
        if argument == "-b" {
            best_move = true;
        }
        if argument == "-a" {
            all_responses = true;
        }
        if argument == "-l" {
            legal_moves = true;
        }
        if argument == "-c" {
            colorize = true;
        }
    }

    let interactive = !all_responses && !best_move && !legal_moves;

    if legal_moves {
        for legal_move in starting_board.legal_moves().iter() {
            println!("{}", legal_move);
        }
    }

    if best_move {
        print_best_move(starting_player, &mut starting_board);
    }

    if all_responses {
        print_all_responses(starting_player, &mut starting_board, colorize);
    }

    if interactive {
        let mut player = starting_player;
        let mut turn_counter = 1;
        loop {
            println!("=================== Turn {} ===================", turn_counter);
            let moves = starting_board.legal_moves();
            if moves.is_empty() {
                println!("No moves left, {:?} wins", player.opponent());
                break;
            }
            println!("{}", starting_board);
            for (i, legal_move) in moves.iter().enumerate() {
                println!("{} {}", i, legal_move);
            }
            println!("It's {:?}'s turn. What move?", player);
            let mut input_move = String::new();
            io::stdin().read_line(&mut input_move).ok().expect("Failed to read line");
            let input_move = input_move.trim();
            if input_move == "analyze" || input_move == "a" {
                print_all_responses(player, &mut starting_board, colorize);
            } else if input_move == "best" || input_move == "b" {
                print_best_move(player, &mut starting_board);
            } else {
                let input_move: usize = match input_move.trim().parse() {
                    Ok(num) => num,
                    Err(_) => { println!("Not a number."); continue },
                };
                match moves.get(input_move) {
                    Some(legal_move) => {
                        starting_board.make_move(*legal_move);
                        player = player.opponent();
                        turn_counter += 1;
                    },
                    None => println!("Move not found.")
                }
            }
        }
    }
}
<commit_msg>simplify alpha beta to just game_result<commit_after>extern crate monorail;
extern crate term;

use monorail::action::Move;
use monorail::board::Board;
use monorail::player::Player;
use std::env;
use std::io;

#[derive(Copy, Clone, Debug)]
enum GameResult {
    JunSeokWin,
    YeonSeungWin,
}

impl GameResult {
    fn win_for(&self, p: Player) -> bool {
        match (*self, p) {
            (GameResult::JunSeokWin, Player::JunSeok) => true,
            (GameResult::JunSeokWin, _) => false,
            (GameResult::YeonSeungWin, Player::YeonSeung) => true,
            (GameResult::YeonSeungWin, _) => false,
        }
    }
}

fn game_result(player: Player, board: &mut Board) -> (GameResult, Option<Move>) {
    let moves = board.legal_moves();
    // There are no more moves, which means my opponent completed the railroad.
    // So I lose.
    if moves.is_empty() {
        return match player {
            Player::YeonSeung => (GameResult::JunSeokWin, None),
            Player::JunSeok => (GameResult::YeonSeungWin, None),
        }
    }

    for possible_move in moves.iter() {
        board.make_move(*possible_move);
        let (reply, _) = game_result(player.opponent(), board);
        board.undo_move(*possible_move);

        // If I have any move that forces a win, I use that move to win.
        // We can return early from the search.
        match (player, reply) {
            (Player::YeonSeung, GameResult::YeonSeungWin) => return (reply, Some(*possible_move)),
            (Player::JunSeok, GameResult::JunSeokWin) => return (reply, Some(*possible_move)),
            _ => (),
        }
    }

    // I have no move that forces a win, therefore I must have lost.
    match player {
        Player::YeonSeung => (GameResult::JunSeokWin, None),
        Player::JunSeok => (GameResult::YeonSeungWin, None),
    }
}

fn print_result(result: GameResult, color: term::color::Color, colorize: bool) {
    if colorize {
        let mut t = term::stdout().unwrap();
        t.fg(color).unwrap();
        t.attr(term::Attr::Bold).unwrap();
        writeln!(t, "{:?}", result).unwrap();
        t.reset().unwrap();
    } else {
        println!("{:?}", result);
    }
}

fn print_all_responses(player: Player, starting_board: &mut Board, colorize: bool) {
    for legal_move in starting_board.legal_moves().iter() {
        print!("If {:?} does: {}, ", player, legal_move);
        starting_board.make_move(*legal_move);
        let (result, best_move) = game_result(player.opponent(), starting_board);
        if result.win_for(player) {
            print_result(result, term::color::BLUE, colorize);
            println!("{}", starting_board);
        } else if let Some(opponent_move) = best_move {
            print!("{:?} does: {}, ", player.opponent(), opponent_move);
            print_result(result, term::color::RED, colorize);
            starting_board.make_move(opponent_move);
            println!("{}", starting_board);
            starting_board.undo_move(opponent_move);
        } else {
            panic!("no move?");
        }
        starting_board.undo_move(*legal_move);
    }
}

fn print_best_move(player: Player, starting_board: &mut Board) {
    let (result, best_move) = game_result(player, starting_board);
    println!("{:?}", result);
    match best_move {
        Some(x) => {
            println!("{}", x);
            starting_board.make_move(x);
            println!("{}", starting_board);
            starting_board.undo_move(x);
        },
        None => println!("No move"),
    }
}

fn main() {
    let mut starting_board = Board::new(
        [
            [false,  true,  true,  true, false],
            [false, false, false,  true, false],
            [false, false, false,  true, false],
            [false, false, false, false, false],
        ],
        None,
    );
    let starting_player = Player::YeonSeung;

    let mut all_responses = false;
    let mut best_move = false;
    let mut legal_moves = false;
    let mut colorize = false;

    for argument in env::args() {
        if argument == "-b" {
            best_move = true;
        }
        if argument == "-a" {
            all_responses = true;
        }
        if argument == "-l" {
            legal_moves = true;
        }
        if argument == "-c" {
            colorize = true;
        }
    }

    let interactive = !all_responses && !best_move && !legal_moves;

    if legal_moves {
        for legal_move in starting_board.legal_moves().iter() {
            println!("{}", legal_move);
        }
    }

    if best_move {
        print_best_move(starting_player, &mut starting_board);
    }

    if all_responses {
        print_all_responses(starting_player, &mut starting_board, colorize);
    }

    if interactive {
        let mut player = starting_player;
        let mut turn_counter = 1;
        loop {
            println!("=================== Turn {} ===================", turn_counter);
            let moves = starting_board.legal_moves();
            if moves.is_empty() {
                println!("No moves left, {:?} wins", player.opponent());
                break;
            }
            println!("{}", starting_board);
            for (i, legal_move) in moves.iter().enumerate() {
                println!("{} {}", i, legal_move);
            }
            println!("It's {:?}'s turn. What move?", player);
            let mut input_move = String::new();
            io::stdin().read_line(&mut input_move).ok().expect("Failed to read line");
            let input_move = input_move.trim();
            if input_move == "analyze" || input_move == "a" {
                print_all_responses(player, &mut starting_board, colorize);
            } else if input_move == "best" || input_move == "b" {
                print_best_move(player, &mut starting_board);
            } else {
                let input_move: usize = match input_move.trim().parse() {
                    Ok(num) => num,
                    Err(_) => { println!("Not a number."); continue },
                };
                match moves.get(input_move) {
                    Some(legal_move) => {
                        starting_board.make_move(*legal_move);
                        player = player.opponent();
                        turn_counter += 1;
                    },
                    None => println!("Move not found.")
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate iron;
extern crate rustc_serialize;
extern crate router;

use iron::prelude::*;
use rand::Rng;
use router::Router;

fn pick_response(name: String) -> String {
  let num = rand::thread_rng().gen_range(1, 12);

  let prefixes = vec!["Asylum", "Bell", "Black", "Capra", "Ceaseless", "Centipede", "Chaos", "Crossbreed", "Dark Sun", "Slayer", "Executioner", "Gaping", "Gravelord", "Iron", "Cinder", "Father", "Abyss", "Moonlight", "Sanctuary", "Stray", "Taurus", "Armoured", "Golden", "Crystal", "Giant", "Undead", "Giant Undead", "Hellkite", "Parasitic", "Prowling", "Prince", "Grey", "Maneater", "Iron", "Paladin", "Xanthous", "Marvellous", "Big Hat", "Black Iron", "Crestfallen", "Darkstalker", "Gravelord", "Hawkeye", "Kingseeker", "Lord\"s Blade", "Stone", "Silent", "Belfry", "Captain", "Emerald", "Grave Warden", "Lonesome", "Manscorpion", "Hag", "Mild Mannered", "Royal", "Sorcerer", "Sparkling", "Steady Hand", "Old", "Ruin", "Old Iron", "Covetous", "Baleful", "Prowling", "Ancient", "Burnt", "Slumbering", "Ivory", "Fume", "Sir", "Nameless", "Pilgrim", "Jester", "Ashen", "Abbess", "Rapacious", "Drifter", "Woodland Child", "Peculiar", "Holy", "Yellowfinger", "Longfinger", "Knight-Slayer", "Curse-Rotted", "Deacon", "High Lord", "Old Demon", "Pontiff", "Boreal", "Unbreakable", "Ringfinger"];
  let types = vec!["Demon", "Gargoyle", "Dragon", "Witch", "Golem", "Knight", "Wolf", "Butcher", "Tusk", "Golem", "Rat", "Hydra", "Wall Hugger", "Prince", "Slayer", "King", "Blacksmith", "Princess", "Merchant", "Scholar", "Oracle", "Guard", "Captain", "Chancellor", "Herald", "Housekeeper", "Laddersmith", "Manscorpion", "Warrior", "Trader", "Lord", "Sentinel", "Queen", "Ogre", "Denizen", "Seeker", "Watcher", "Devourer", "Outrider Knight", "High Priestess", "Mother"];
  let suffixes = vec!["of Chaos", "of the Abyss", "of Cinder", "of Thorns", "of the Darkroot Wood", "of Astora", "of Zena", "of Oolacile", "of Vinheim", "of Sunlight", "of Carim", "of the Great Swamp", "of Thorolund", "of Izalith", "of the East", "of Catarina", "of the First Sin", "of Jugo", "of Mirrah", "of Lanafir", "of Olaphis", "of Song", "of Londor", "of the Spurned", "of the Sunless Realms", "of Carim", "of the Boreal Valley", "of the Deep", "of Lothric Castle", "of Courland", "of Rebirth"];
  let nicknames = vec!["the Scaleless", "the Great", "the Rock", "the Crow", "the Cartographer", "the Wanderer", "the Pardoner", "the Outcast", "the Armourer", "the Crestfallen", "the Lost", "the Ruined", "the Baleful", "the King\"s Pet", "the Squalid", "the Explorer", "the Butcher", "the Deserter", "the Hushed", "the Giant", "the Consumed"];

  let prefix = prefixes[rand::thread_rng().gen_range(0, prefixes.len())];
  let name_type = types[rand::thread_rng().gen_range(0, types.len())];
  let suffix = suffixes[rand::thread_rng().gen_range(0, suffixes.len())];
  let nickname = nicknames[rand::thread_rng().gen_range(0, nicknames.len())];

  let response = match num {
    1 => format!("{} {}", prefix, name_type),
    2 => format!("{} {}", prefix, name),
    3 => format!("{} {}, {} {}", name, nickname, prefix, name_type),
    4 => format!("{}, {} {}", name, name_type, suffix),
    5 => format!("{} {}", name, suffix),
    6 => format!("{} {} {}", name, nickname, suffix),
    7 => format!("{} {} {}", prefix, name_type, name),
    8 => format!("{} {} {}", prefix, name, nickname),
    9 => format!("{} {}, {} {}", prefix, name, name_type, suffix),
    10 => format!("{}, {} {}", name, nickname, name_type),
    11 => format!("{} {}", name_type, name),
    _ => format!("{}", name)
  };

  response.to_string()
}

fn get_name(name: String) -> String {
  pick_response(name)
}

fn get_default_name() -> String {
  pick_response("Brian".to_string())
}

mod handlers {
  use iron::prelude::*;
  use iron::status;
  use iron::mime::Mime;
  use rustc_serialize::json;
  use std::io::Read;
  use router::Router;
  use super::{ get_name, get_default_name };

  #[derive(RustcDecodable)]
  struct JsonRequest {
    name: String
  }

  #[derive(RustcEncodable, RustcDecodable)]
  struct JsonResponse {
    name: String,
    success: bool,
    error_message: String
  }

  impl JsonResponse {
    fn success(name: String) -> Self {
      JsonResponse { name: name, success: true, error_message: "".to_string() }
    }

    fn error(msg: String) -> Self {
      JsonResponse { name: "".to_string(), success: false, error_message: msg }
    }
  }

  pub fn default(_: &mut Request) -> IronResult<Response> {
    let response = JsonResponse::success(get_default_name());
    let out = json::encode(&response).expect("Error encoding response");

    let content_type = "application/json".parse::<Mime>().expect("Failed to parse content type");
    Ok(Response::with((content_type, status::Ok, out)))
  }

  pub fn get_handler(req: &mut Request) -> IronResult<Response> {
    let ref name = req.extensions.get::<Router>().unwrap().find("name").unwrap_or("/");
    let response = JsonResponse::success(get_name((*name).to_string()));
    let out = json::encode(&response).expect("Error encoding response");

    let content_type = "application/json".parse::<Mime>().expect("Failed to parse content type");
    Ok(Response::with((content_type, status::Ok, out)))
  }

  pub fn post_handler(req: &mut Request) -> IronResult<Response> {
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).expect("Failed to read request body");

    // let incoming: JsonResponse = json::decode(&payload).ok().expect("Invalid JSON in POST body");
    let out = match json::decode(&payload) {
      Err(e) => {
        let response = JsonResponse::error(format!("Error parsing JSON: {:?}", e));
        json::encode(&response).ok().expect("Error encoding response")
      },
      Ok(incoming) => {
        let converted: JsonRequest = incoming;
        let response = JsonResponse::success(get_name(converted.name));
        json::encode(&response).expect("Error encoding response")
      }
    };

    let content_type = "application/json".parse::<Mime>().expect("Failed to parse content type");
    Ok(Response::with((content_type, status::Ok, out)))
  }
}

fn main() {
  let mut router = Router::new();
  router.get("/", handlers::default, "index");
  router.get("/:name", handlers::get_handler, "name");
  router.post("/", handlers::post_handler, "post_name");

  println!("Listening on localhost:3009");
  Iron::new(router).http("localhost:3009").ok();
}

#[cfg(test)]
mod test {
  #[test]
  fn generates_name() {
    let name = super::pick_response("Brian".to_string());
    assert!(name.len() > 0);
  }

  // extern crate hyper;

  // use iron::prelude::*;
  // use iron::method::Method;
  // use iron::Url;
  // use iron::Headers;
  // use iron::TypeMap;
  // use iron::request::Body;
  // use std::net::{IpAddr, Ipv4Addr, SocketAddr};

  // #[test]
  // fn default_handler() {
  //   // make a fake request
  //   let mut req: Request = Request {
  //     url: Url::parse("http://example.com").unwrap(),
  //     remote_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 80),
  //     headers: Headers::new(),
  //     local_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 80),
  //     body: Body::new(),
  //     method: Method::Get,
  //     extensions: TypeMap::new()
  //   };

  //   let res = super::handler(&mut req);
  //   println!("{:?}", res);
  // }
}<commit_msg>move to mod<commit_after>extern crate rand;
extern crate iron;
extern crate rustc_serialize;
extern crate router;

use iron::prelude::*;
use router::Router;

mod name_gen {
  use rand;
  use rand::Rng; // trait

  pub fn pick_response(name: String) -> String {
    let num = rand::thread_rng().gen_range(1, 12);

    let prefixes = vec!["Asylum", "Bell", "Black", "Capra", "Ceaseless", "Centipede", "Chaos", "Crossbreed", "Dark Sun", "Slayer", "Executioner", "Gaping", "Gravelord", "Iron", "Cinder", "Father", "Abyss", "Moonlight", "Sanctuary", "Stray", "Taurus", "Armoured", "Golden", "Crystal", "Giant", "Undead", "Giant Undead", "Hellkite", "Parasitic", "Prowling", "Prince", "Grey", "Maneater", "Iron", "Paladin", "Xanthous", "Marvellous", "Big Hat", "Black Iron", "Crestfallen", "Darkstalker", "Gravelord", "Hawkeye", "Kingseeker", "Lord\"s Blade", "Stone", "Silent", "Belfry", "Captain", "Emerald", "Grave Warden", "Lonesome", "Manscorpion", "Hag", "Mild Mannered", "Royal", "Sorcerer", "Sparkling", "Steady Hand", "Old", "Ruin", "Old Iron", "Covetous", "Baleful", "Prowling", "Ancient", "Burnt", "Slumbering", "Ivory", "Fume", "Sir", "Nameless", "Pilgrim", "Jester", "Ashen", "Abbess", "Rapacious", "Drifter", "Woodland Child", "Peculiar", "Holy", "Yellowfinger", "Longfinger", "Knight-Slayer", "Curse-Rotted", "Deacon", "High Lord", "Old Demon", "Pontiff", "Boreal", "Unbreakable", "Ringfinger"];
    let types = vec!["Demon", "Gargoyle", "Dragon", "Witch", "Golem", "Knight", "Wolf", "Butcher", "Tusk", "Golem", "Rat", "Hydra", "Wall Hugger", "Prince", "Slayer", "King", "Blacksmith", "Princess", "Merchant", "Scholar", "Oracle", "Guard", "Captain", "Chancellor", "Herald", "Housekeeper", "Laddersmith", "Manscorpion", "Warrior", "Trader", "Lord", "Sentinel", "Queen", "Ogre", "Denizen", "Seeker", "Watcher", "Devourer", "Outrider Knight", "High Priestess", "Mother"];
    let suffixes = vec!["of Chaos", "of the Abyss", "of Cinder", "of Thorns", "of the Darkroot Wood", "of Astora", "of Zena", "of Oolacile", "of Vinheim", "of Sunlight", "of Carim", "of the Great Swamp", "of Thorolund", "of Izalith", "of the East", "of Catarina", "of the First Sin", "of Jugo", "of Mirrah", "of Lanafir", "of Olaphis", "of Song", "of Londor", "of the Spurned", "of the Sunless Realms", "of Carim", "of the Boreal Valley", "of the Deep", "of Lothric Castle", "of Courland", "of Rebirth"];
    let nicknames = vec!["the Scaleless", "the Great", "the Rock", "the Crow", "the Cartographer", "the Wanderer", "the Pardoner", "the Outcast", "the Armourer", "the Crestfallen", "the Lost", "the Ruined", "the Baleful", "the King\"s Pet", "the Squalid", "the Explorer", "the Butcher", "the Deserter", "the Hushed", "the Giant", "the Consumed"];

    let prefix = prefixes[rand::thread_rng().gen_range(0, prefixes.len())];
    let name_type = types[rand::thread_rng().gen_range(0, types.len())];
    let suffix = suffixes[rand::thread_rng().gen_range(0, suffixes.len())];
    let nickname = nicknames[rand::thread_rng().gen_range(0, nicknames.len())];

    let response = match num {
      1 => format!("{} {}", prefix, name_type),
      2 => format!("{} {}", prefix, name),
      3 => format!("{} {}, {} {}", name, nickname, prefix, name_type),
      4 => format!("{}, {} {}", name, name_type, suffix),
      5 => format!("{} {}", name, suffix),
      6 => format!("{} {} {}", name, nickname, suffix),
      7 => format!("{} {} {}", prefix, name_type, name),
      8 => format!("{} {} {}", prefix, name, nickname),
      9 => format!("{} {}, {} {}", prefix, name, name_type, suffix),
      10 => format!("{}, {} {}", name, nickname, name_type),
      11 => format!("{} {}", name_type, name),
      _ => format!("{}", name)
    };

    response.to_string()
  }

  pub fn get_name(name: String) -> String {
    pick_response(name)
  }

  pub fn get_default_name() -> String {
    pick_response("Brian".to_string())
  }
}

mod handlers {
  use iron::prelude::*;
  use iron::status;
  use iron::mime::Mime;
  use rustc_serialize::json;
  use std::io::Read;
  use router::Router;
  use name_gen::{ get_name, get_default_name };

  #[derive(RustcDecodable)]
  struct JsonRequest {
    name: String
  }

  #[derive(RustcEncodable, RustcDecodable)]
  struct JsonResponse {
    name: String,
    success: bool,
    error_message: String
  }

  impl JsonResponse {
    fn success(name: String) -> Self {
      JsonResponse { name: name, success: true, error_message: "".to_string() }
    }

    fn error(msg: String) -> Self {
      JsonResponse { name: "".to_string(), success: false, error_message: msg }
    }
  }

  pub fn default(_: &mut Request) -> IronResult<Response> {
    let response = JsonResponse::success(get_default_name());
    let out = json::encode(&response).expect("Error encoding response");

    let content_type = "application/json".parse::<Mime>().expect("Failed to parse content type");
    Ok(Response::with((content_type, status::Ok, out)))
  }

  pub fn get_handler(req: &mut Request) -> IronResult<Response> {
    let ref name = req.extensions.get::<Router>().unwrap().find("name").unwrap_or("/");
    let response = JsonResponse::success(get_name((*name).to_string()));
    let out = json::encode(&response).expect("Error encoding response");

    let content_type = "application/json".parse::<Mime>().expect("Failed to parse content type");
    Ok(Response::with((content_type, status::Ok, out)))
  }

  pub fn post_handler(req: &mut Request) -> IronResult<Response> {
    let mut payload = String::new();
    req.body.read_to_string(&mut payload).expect("Failed to read request body");

    let out = match json::decode(&payload) {
      Err(e) => {
        let response = JsonResponse::error(format!("Error parsing JSON: {:?}", e));
        json::encode(&response).ok().expect("Error encoding response")
      },
      Ok(incoming) => {
        let converted: JsonRequest = incoming;
        let response = JsonResponse::success(get_name(converted.name));
        json::encode(&response).expect("Error encoding response")
      }
    };

    let content_type = "application/json".parse::<Mime>().expect("Failed to parse content type");
    Ok(Response::with((content_type, status::Ok, out)))
  }
}

fn main() {
  let mut router = Router::new();
  router.get("/", handlers::default, "index");
  router.get("/:name", handlers::get_handler, "name");
  router.post("/", handlers::post_handler, "post_name");

  println!("Listening on localhost:3009");
  Iron::new(router).http("localhost:3009").ok();
}

#[cfg(test)]
mod test {
  #[test]
  fn generates_name() {
    let name = super::pick_response("Brian".to_string());
    assert!(name.len() > 0);
  }
}<|endoftext|>


<commit_before>use std::boxed::Box;

#[derive(Debug)]
struct SearchTree<T> {
    left: Option<Box<SearchTree<T>>>,
    right: Option<Box<SearchTree<T>>>,
    key: T,
}

impl<T> SearchTree<T> where T: std::fmt::Debug + std::cmp::Eq + std::cmp::PartialOrd + std::clone::Clone {
    fn inorder_tree(&self) {
        if let Some(ref tree) = self.left {
            tree.inorder_tree();
        }
        println!("self.key = {:#?}", self.key);
        if let Some(ref tree) = self.right {
            tree.inorder_tree();
        }
    }

    fn search_tree(&self, key: T ) -> Option<T> {
        if self.key == key {
            return Some(self.key.clone());
        }

        if key < self.key {
            match self.left {
                Some(ref tree) => tree.search_tree(key),
                None => None
            }
        } else {
            match self.right {
                Some(ref tree) => tree.search_tree(key),
                None => None
            }
        }
    }
    fn minimum_tree(&self) -> T {
        match self.left {
            Some(ref tree) => tree.minimum_tree(),
            None => self.key.clone()
        }
    }

    fn maximum_tree(&self) -> T {
        match self.right {
            Some(ref tree) => tree.maximum_tree(),
            None => self.key.clone()
        }
    }

    fn insert_tree(&mut self, tree:SearchTree<T>) {

        if self.key <= tree.key {
            if let Some(ref mut left) = self.left {
                left.insert_tree(tree);
            } else {
                self.left = Some(Box::new(tree));
            }
        } else {
            if let Some(ref mut right) = self.right {
                right.insert_tree(tree);
            } else {
                self.right = Some(Box::new(tree));
            }
        }
    }

}

fn main() {
    let left = SearchTree {
        left: None,
        right: None,
        key: 32,
    };

    let right = SearchTree {
        left: None,
        right: None,
        key: 43,
    };

    let mut root = SearchTree {
        left: Some(Box::new(left)),
        right: Some(Box::new(right)),
        key: 40,
    };

    root.inorder_tree();

    let tree = root.search_tree(43);
    match tree {
        Some(t) => println!("t = {:#?}", t),
        None => println!(" None "),

    }

    let min = root.minimum_tree();
    println!("min = {:#?}", min);

    let max = root.maximum_tree();
    println!("max = {:#?}", max);

    let mut will_insert_tree = SearchTree {
        left: None,
        right: None,
        key: 41,
    };

    root.insert_tree(will_insert_tree);

    println!("root = {:#?}", root);

    println!("root.search_tree(40) = {:#?}", root.search_tree(41));

}

<commit_msg>bugfix<commit_after>use std::boxed::Box;

#[derive(Debug)]
struct SearchTree<T> {
    left: Option<Box<SearchTree<T>>>,
    right: Option<Box<SearchTree<T>>>,
    key: T,
}

impl<T> SearchTree<T> where T: std::fmt::Debug + std::cmp::Eq + std::cmp::PartialOrd + std::clone::Clone {
    fn inorder(&self) {
        if let Some(ref tree) = self.left {
            tree.inorder();
        }
        println!("self.key = {:#?}", self.key);
        if let Some(ref tree) = self.right {
            tree.inorder();
        }
    }

    fn search(&self, key: T ) -> Option<T> {
        if self.key == key {
            return Some(self.key.clone());
        }

        if key < self.key {
            match self.left {
                Some(ref tree) => tree.search(key),
                None => None
            }
        } else {
            match self.right {
                Some(ref tree) => tree.search(key),
                None => None
            }
        }
    }
    fn minimum(&self) -> T {
        match self.left {
            Some(ref tree) => tree.minimum(),
            None => self.key.clone()
        }
    }

    fn maximum(&self) -> T {
        match self.right {
            Some(ref tree) => tree.maximum(),
            None => self.key.clone()
        }
    }

    fn insert(&mut self, tree:SearchTree<T>) {

        if self.key >= tree.key {
            if let Some(ref mut left) = self.left {
                left.insert(tree);
            } else {
                self.left = Some(Box::new(tree));
            }
        } else {
            if let Some(ref mut right) = self.right {
                right.insert(tree);
            } else {
                self.right = Some(Box::new(tree));
            }
        }
    }

    fn delete(&mut self, key: T) {

    }

}

fn main() {
    let left = SearchTree {
        left: None,
        right: None,
        key: 32,
    };

    let right = SearchTree {
        left: None,
        right: None,
        key: 43,
    };

    let mut root = SearchTree {
        left: Some(Box::new(left)),
        right: Some(Box::new(right)),
        key: 40,
    };

    root.inorder();

    let tree = root.search(43);
    match tree {
        Some(t) => println!("t = {:#?}", t),
        None => println!(" None "),

    }

    let min = root.minimum();
    println!("min = {:#?}", min);

    let max = root.maximum();
    println!("max = {:#?}", max);

    let mut will_insert_tree = SearchTree {
        left: None,
        right: None,
        key: 41,
    };

    root.insert(will_insert_tree);

    println!("root = {:#?}", root);

    println!("root.search_tree(41) = {:#?}", root.search(41));

}

<|endoftext|>


<commit_before>use std::env;

#[macro_use]
pub mod utils;

extern crate zwreec;

fn main() {
    log_info!("main started");

    // handling commandline parameters
    let args: Vec<String> = env::args().collect();

    let mut input_file_name: &str;
    let mut output_file_name: &str;

    match args.len() {
        1 => {
            input_file_name = "a.in";
            output_file_name = "a.out";
        },
        3 => {
            input_file_name = &args[1];
            output_file_name = &args[2];
        },
        _ => {
            help();
            return;
        }
    };

    // call library
    zwreec::compile(input_file_name, output_file_name);

    // only for testing
    log_verbose!("(1) {}", zwreec::frontend::temp_hello());
    log_verbose!("(2) {}", zwreec::backend::temp_hello());
    log_verbose!("(3) {}", zwreec::file::temp_hello());

    log_info!("main finished");
}

fn help() {
    log_error!("invalid arguments");
    log_info!("usage:\n    zwreec <input_file> <output_file>");
}
<commit_msg>Use new logger and new macros<commit_after>use std::env;
use std::fs::File;

mod utils;
use self::utils::logger;

extern crate zwreec;
#[macro_use] extern crate log;
extern crate time;
extern crate term;

fn main() {
    //early init

    //let _ = SimpleLogger::init(LogLevelFilter::Info);
    let _ = logger::CombinedLogger::init(
        vec![
            logger::FileLogger::new(logger::LogLevelFilter::Trace, File::create("zwreec.log").unwrap()),
            logger::TermLogger::new(logger::LogLevelFilter::Info),
        ]
    );

    info!("main started");

    // handling commandline parameters
    let args: Vec<String> = env::args().collect();

    let mut input_file_name: &str;
    let mut output_file_name: &str;

    match args.len() {
        1 => {
            input_file_name = "a.in";
            output_file_name = "a.out";
        },
        3 => {
            input_file_name = &args[1];
            output_file_name = &args[2];
        },
        _ => {
            help();
            return;
        }
    };

    // call library
    zwreec::compile(input_file_name, output_file_name);

    // only for testing
    debug!("(1) {}", zwreec::frontend::temp_hello());
    debug!("(2) {}", zwreec::backend::temp_hello());
    debug!("(3) {}", zwreec::file::temp_hello());

    info!("main finished");
}

fn help() {
    error!("invalid arguments");
    info!("usage:\n    zwreec <input_file> <output_file>");
}
<|endoftext|>


<commit_before>extern crate bytes;
extern crate env_logger;
extern crate mio;
#[macro_use]
extern crate log;
#[macro_use]
extern crate clap;
extern crate failure;
extern crate slab;

use clap::{App, Arg};
use failure::Error;
use failure::ResultExt;
use mio::net::{TcpListener, TcpStream};
use slab::Slab;
use std::collections::VecDeque;
use std::io::{Read, Write};
use std::ops;

#[derive(Debug)]
enum MiChatCommand {
    Broadcast(String),
    NewConnection(TcpStream),
}

struct MiChat {
    connections: Slab<EventHandler>,
}

trait RuleHandler {
    fn handle_event(&mut self, _event_loop: &mut mio::Poll, events: mio::Ready);
    fn register(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error>;
    fn deregister(&self, event_loop: &mut mio::Poll) -> Result<(), Error>;
    fn process_rules(
        &mut self,
        event_loop: &mut mio::Poll,
        to_parent: &mut FnMut(MiChatCommand),
    ) -> Result<(), Error>;
    fn should_close(&self) -> bool;
}

impl MiChat {
    fn new() -> MiChat {
        MiChat {
            connections: Slab::new(),
        }
    }

    fn listen(&mut self, event_loop: &mut mio::Poll, listener: TcpListener) -> Result<(), Error> {
        let token = {
            let e = self.connections.vacant_entry();
            let token = mio::Token(e.key());
            let l = EventHandler::Listener(Listener::new(listener, token));
            e.insert(l);
            token
        };
        &self.connections[token.into()].register(event_loop, token)?;
        Ok(())
    }

    fn process_action(&mut self, src: usize, msg: MiChatCommand, event_loop: &mut mio::Poll) {
        trace!("{:p}; from {:?}; got {:?}", self, src, msg);
        match msg {
            MiChatCommand::Broadcast(s) => self.process_broadcast(s),
            MiChatCommand::NewConnection(socket) => self.process_new_connection(event_loop, socket),
        }
    }

    fn process_broadcast(&mut self, s: String) {
        for c in self.client_connections_mut() {
            c.enqueue(&s);
        }
    }

    fn process_new_connection(&mut self, event_loop: &mut mio::Poll, socket: mio::tcp::TcpStream) {
        let token = {
            let e = self.connections.vacant_entry();
            let token = mio::Token(e.key());
            let l = EventHandler::Conn(Connection::new(socket, token));
            e.insert(l);
            token
        };
        &self.connections[token.into()].register(event_loop, token);
    }

    fn client_connections_mut<'a>(&'a mut self) -> impl Iterator<Item = &'a mut Connection> + 'a {
        self.connections.iter_mut().filter_map(|(_, it)| match it {
            &mut EventHandler::Conn(ref mut c) => Some(c),
            _ => None,
        })
    }
}

#[derive(Debug)]
struct Connection {
    socket: TcpStream,
    sock_status: mio::Ready,
    token: mio::Token,
    read_buf: Vec<u8>,
    read_eof: bool,
    write_buf: Vec<u8>,
}

impl RuleHandler for Connection {
    fn register(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error> {
        event_loop
            .register(
                &self.socket,
                token,
                mio::Ready::readable(),
                mio::PollOpt::edge() | mio::PollOpt::oneshot(),
            ).context("event loop register")?;
        Ok(())
    }
    fn deregister(&self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        event_loop.deregister(&self.socket)?;
        Ok(())
    }

    // Event updates arrive here
    fn handle_event(&mut self, _event_loop: &mut mio::Poll, events: mio::Ready) {
        self.sock_status.insert(events);
        info!(
            "Connection::handle_event: {:?}; this time: {:?}; now: {:?}",
            self.socket.peer_addr(),
            events,
            self.sock_status
        );
    }

    // actions are processed here on down.

    fn process_rules(
        &mut self,
        event_loop: &mut mio::Poll,
        to_parent: &mut FnMut(MiChatCommand),
    ) -> Result<(), Error> {
        if self.sock_status.is_readable() {
            self.sock_status.remove(mio::Ready::readable());
            self.read()?;
        }

        self.process_buffer(to_parent);

        if self.sock_status.is_writable() {
            self.sock_status.remove(mio::Ready::writable());
            self.write()?;
        }

        if !self.should_close() {
            self.reregister(event_loop)?;
        }

        Ok(())
    }

    fn should_close(&self) -> bool {
        self.read_eof && self.write_buf.is_empty()
    }
}

impl Connection {
    fn new(socket: TcpStream, token: mio::Token) -> Connection {
        Connection {
            socket: socket,
            sock_status: mio::Ready::empty(),
            token: token,
            read_buf: Vec::with_capacity(1024),
            write_buf: Vec::new(),
            read_eof: false,
        }
    }
    fn process_buffer(&mut self, to_parent: &mut FnMut(MiChatCommand)) {
        let mut prev = 0;
        info!(
            "{:?}: Read buffer: {:?}",
            self.socket.peer_addr(),
            self.read_buf
        );
        for n in self.read_buf.iter().enumerate().filter_map(|(i, e)| {
            if *e == '\n' as u8 {
                Some(i)
            } else {
                None
            }
        }) {
            info!(
                "{:?}: Pos: {:?}; chunk: {:?}",
                self.socket.peer_addr(),
                n,
                &self.read_buf[prev..n]
            );
            let s = String::from_utf8_lossy(&self.read_buf[prev..n]).to_string();
            let cmd = MiChatCommand::Broadcast(s);
            info!("Send! {:?}", cmd);
            to_parent(cmd);
            prev = n + 1;
        }
        let remainder = self.read_buf[prev..].to_vec();
        info!(
            "{:?}: read Remainder: {}",
            self.socket.peer_addr(),
            remainder.len()
        );
        self.read_buf = remainder;
    }

    fn read(&mut self) -> Result<(), Error> {
        let mut abuf = vec![0; 1024];
        match self.socket.read(&mut abuf).context("Reading socket")? {
            0 => {
                info!("{:?}: EOF!", self.socket.peer_addr());
                self.read_eof = true;
                Ok(())
            }
            n => {
                info!("{:?}: Read {}bytes", self.socket.peer_addr(), n);
                self.read_buf.extend(&abuf[0..n]);
                Ok(())
            }
        }
    }

    fn write(&mut self) -> Result<(), Error> {
        let n = self
            .socket
            .write(&mut self.write_buf)
            .context("writing buffer")?;
        info!(
            "{:?}: Wrote {} of {} in buffer",
            self.socket.peer_addr(),
            n,
            self.write_buf.len()
        );
        self.write_buf = self.write_buf[n..].to_vec();
        info!(
            "{:?}: Now {:?}b",
            self.socket.peer_addr(),
            self.write_buf.len()
        );
        Ok(())
    }

    fn reregister(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        let mut flags = mio::Ready::readable();
        if !self.write_buf.is_empty() {
            flags.insert(mio::Ready::writable());
        }
        info!("Registering {:?} with {:?}", self, flags);

        event_loop
            .reregister(&self.socket, self.token, flags, mio::PollOpt::oneshot())
            .context("EventLoop#reregister")?;

        Ok(())
    }

    fn enqueue(&mut self, s: &str) {
        self.write_buf.extend(s.as_bytes());
        self.write_buf.push('\n' as u8);
    }
}

#[derive(Debug)]
struct Listener {
    listener: TcpListener,
    sock_status: mio::Ready,
    token: mio::Token,
}

impl Listener {
    fn new(listener: TcpListener, token: mio::Token) -> Listener {
        Listener {
            listener: listener,
            sock_status: mio::Ready::empty(),
            token: token,
        }
    }
    fn reregister(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error> {
        event_loop
            .reregister(
                &self.listener,
                token,
                mio::Ready::readable(),
                mio::PollOpt::edge() | mio::PollOpt::oneshot(),
            ).context("Register listener")?;
        Ok(())
    }
}

impl RuleHandler for Listener {
    fn register(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error> {
        event_loop
            .register(
                &self.listener,
                token,
                mio::Ready::readable(),
                mio::PollOpt::edge() | mio::PollOpt::oneshot(),
            ).context("Register listener")?;
        Ok(())
    }
    fn deregister(&self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        event_loop.deregister(&self.listener)?;
        Ok(())
    }

    fn handle_event(&mut self, _event_loop: &mut mio::Poll, events: mio::Ready) {
        assert!(events.is_readable());
        self.sock_status.insert(events);
        info!(
            "Listener::handle_event: {:?}; this time: {:?}; now: {:?}",
            self.listener.local_addr(),
            events,
            self.sock_status
        );
    }
    fn process_rules(
        &mut self,
        event_loop: &mut mio::Poll,
        to_parent: &mut FnMut(MiChatCommand),
    ) -> Result<(), Error> {
        if self.sock_status.is_readable() {
            info!("the listener socket is ready to accept a connection");
            self.sock_status.remove(mio::Ready::readable());
            let (socket, _client) = self.listener.accept().context("Accept listening socket")?;
            let cmd = MiChatCommand::NewConnection(socket);
            to_parent(cmd);

            self.reregister(event_loop, self.token)?;
        }
        Ok(())
    }

    fn should_close(&self) -> bool {
        false
    }
}

#[derive(Debug)]
enum EventHandler {
    Listener(Listener),
    Conn(Connection),
}

impl ops::Deref for EventHandler {
    type Target = RuleHandler;
    fn deref(&self) -> &Self::Target {
        match self {
            &EventHandler::Conn(ref conn) => conn,
            &EventHandler::Listener(ref listener) => listener,
        }
    }
}
impl ops::DerefMut for EventHandler {
    fn deref_mut(&mut self) -> &mut Self::Target {
        match self {
            &mut EventHandler::Conn(ref mut conn) => conn,
            &mut EventHandler::Listener(ref mut listener) => listener,
        }
    }
}

impl MiChat {
    fn ready(&mut self, event_loop: &mut mio::Poll, token: mio::Token, events: mio::Ready) {
        info!("{:?}: {:?}", token, events);
        self.connections[token.into()].handle_event(event_loop, events);
    }

    fn process(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        let mut parent_actions = VecDeque::new();
        let mut failed = Vec::new();
        loop {
            for (idx, conn) in self.connections.iter_mut() {
                if let Err(e) = conn.process_rules(event_loop, &mut |action| {
                    parent_actions.push_back((idx, action))
                }) {
                    failed.push(idx);
                    error!("Error on connection {:?}; Dropping: {:?}", idx, e);
                }

                if conn.should_close() {
                    failed.push(idx);
                    info!("Removing; {:?}", idx);
                }
            }
            for idx in failed.drain(..) {
                let conn = self.connections.remove(idx);
                conn.deregister(event_loop)?;
            }
            // Anything left to process?
            if parent_actions.is_empty() {
                break;
            }

            for (src, action) in parent_actions.drain(..) {
                self.process_action(src, action, event_loop);
            }
        }

        Ok(())
    }

    fn run(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        loop {
            self.run_once(event_loop)?;
        }
    }
    fn run_once(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        let mut events = mio::Events::with_capacity(1024);
        event_loop.poll(&mut events, None)?;
        for ev in &events {
            self.ready(event_loop, ev.token(), ev.readiness())
        }

        self.process(event_loop)
    }
}

fn main() {
    env_logger::init();
    let matches = App::new("michat")
        .arg(
            Arg::with_name("bind")
                .short("l")
                .takes_value(true)
                .required(true),
        ).get_matches();

    let address = value_t_or_exit!(matches.value_of("bind"), std::net::SocketAddr);
    let listener = TcpListener::bind(&address).expect("bind");

    let mut event_loop = mio::Poll::new().expect("Create event loop");
    let mut service = MiChat::new();

    service
        .listen(&mut event_loop, listener)
        .expect("Starting listener");
    info!("running michat listener at: {:?}", address);
    service.run(&mut event_loop).expect("run");
}
<commit_msg>Handle errors in command processor.<commit_after>extern crate bytes;
extern crate env_logger;
extern crate mio;
#[macro_use]
extern crate log;
#[macro_use]
extern crate clap;
extern crate failure;
extern crate slab;

use clap::{App, Arg};
use failure::Error;
use failure::ResultExt;
use mio::net::{TcpListener, TcpStream};
use slab::Slab;
use std::collections::VecDeque;
use std::io::{Read, Write};
use std::ops;

#[derive(Debug)]
enum MiChatCommand {
    Broadcast(String),
    NewConnection(TcpStream),
}

struct MiChat {
    connections: Slab<EventHandler>,
}

trait RuleHandler {
    fn handle_event(&mut self, _event_loop: &mut mio::Poll, events: mio::Ready);
    fn register(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error>;
    fn deregister(&self, event_loop: &mut mio::Poll) -> Result<(), Error>;
    fn process_rules(
        &mut self,
        event_loop: &mut mio::Poll,
        to_parent: &mut FnMut(MiChatCommand),
    ) -> Result<(), Error>;
    fn should_close(&self) -> bool;
}

impl MiChat {
    fn new() -> MiChat {
        MiChat {
            connections: Slab::new(),
        }
    }

    fn listen(&mut self, event_loop: &mut mio::Poll, listener: TcpListener) -> Result<(), Error> {
        let token = {
            let e = self.connections.vacant_entry();
            let token = mio::Token(e.key());
            let l = EventHandler::Listener(Listener::new(listener, token));
            e.insert(l);
            token
        };
        &self.connections[token.into()].register(event_loop, token)?;
        Ok(())
    }

    fn process_action(
        &mut self,
        src: usize,
        msg: MiChatCommand,
        event_loop: &mut mio::Poll,
    ) -> Result<(), Error> {
        trace!("{:p}; from {:?}; got {:?}", self, src, msg);
        match msg {
            MiChatCommand::Broadcast(s) => self.process_broadcast(s)?,
            MiChatCommand::NewConnection(socket) => {
                self.process_new_connection(event_loop, socket)?
            }
        }
        Ok(())
    }

    fn process_broadcast(&mut self, s: String) -> Result<(), Error> {
        for c in self.client_connections_mut() {
            c.enqueue(&s);
        }
        Ok(())
    }

    fn process_new_connection(
        &mut self,
        event_loop: &mut mio::Poll,
        socket: mio::tcp::TcpStream,
    ) -> Result<(), Error> {
        let token = {
            let e = self.connections.vacant_entry();
            let token = mio::Token(e.key());
            let l = EventHandler::Conn(Connection::new(socket, token));
            e.insert(l);
            token
        };
        &self.connections[token.into()].register(event_loop, token)?;
        Ok(())
    }

    fn client_connections_mut<'a>(&'a mut self) -> impl Iterator<Item = &'a mut Connection> + 'a {
        self.connections.iter_mut().filter_map(|(_, it)| match it {
            &mut EventHandler::Conn(ref mut c) => Some(c),
            _ => None,
        })
    }
}

#[derive(Debug)]
struct Connection {
    socket: TcpStream,
    sock_status: mio::Ready,
    token: mio::Token,
    read_buf: Vec<u8>,
    read_eof: bool,
    write_buf: Vec<u8>,
}

impl RuleHandler for Connection {
    fn register(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error> {
        event_loop
            .register(
                &self.socket,
                token,
                mio::Ready::readable(),
                mio::PollOpt::edge() | mio::PollOpt::oneshot(),
            ).context("event loop register")?;
        Ok(())
    }
    fn deregister(&self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        event_loop.deregister(&self.socket)?;
        Ok(())
    }

    // Event updates arrive here
    fn handle_event(&mut self, _event_loop: &mut mio::Poll, events: mio::Ready) {
        self.sock_status.insert(events);
        info!(
            "Connection::handle_event: {:?}; this time: {:?}; now: {:?}",
            self.socket.peer_addr(),
            events,
            self.sock_status
        );
    }

    // actions are processed here on down.

    fn process_rules(
        &mut self,
        event_loop: &mut mio::Poll,
        to_parent: &mut FnMut(MiChatCommand),
    ) -> Result<(), Error> {
        if self.sock_status.is_readable() {
            self.sock_status.remove(mio::Ready::readable());
            self.read()?;
        }

        self.process_buffer(to_parent);

        if self.sock_status.is_writable() {
            self.sock_status.remove(mio::Ready::writable());
            self.write()?;
        }

        if !self.should_close() {
            self.reregister(event_loop)?;
        }

        Ok(())
    }

    fn should_close(&self) -> bool {
        self.read_eof && self.write_buf.is_empty()
    }
}

impl Connection {
    fn new(socket: TcpStream, token: mio::Token) -> Connection {
        Connection {
            socket: socket,
            sock_status: mio::Ready::empty(),
            token: token,
            read_buf: Vec::with_capacity(1024),
            write_buf: Vec::new(),
            read_eof: false,
        }
    }
    fn process_buffer(&mut self, to_parent: &mut FnMut(MiChatCommand)) {
        let mut prev = 0;
        info!(
            "{:?}: Read buffer: {:?}",
            self.socket.peer_addr(),
            self.read_buf
        );
        for n in self.read_buf.iter().enumerate().filter_map(|(i, e)| {
            if *e == '\n' as u8 {
                Some(i)
            } else {
                None
            }
        }) {
            info!(
                "{:?}: Pos: {:?}; chunk: {:?}",
                self.socket.peer_addr(),
                n,
                &self.read_buf[prev..n]
            );
            let s = String::from_utf8_lossy(&self.read_buf[prev..n]).to_string();
            let cmd = MiChatCommand::Broadcast(s);
            info!("Send! {:?}", cmd);
            to_parent(cmd);
            prev = n + 1;
        }
        let remainder = self.read_buf[prev..].to_vec();
        info!(
            "{:?}: read Remainder: {}",
            self.socket.peer_addr(),
            remainder.len()
        );
        self.read_buf = remainder;
    }

    fn read(&mut self) -> Result<(), Error> {
        let mut abuf = vec![0; 1024];
        match self.socket.read(&mut abuf).context("Reading socket")? {
            0 => {
                info!("{:?}: EOF!", self.socket.peer_addr());
                self.read_eof = true;
                Ok(())
            }
            n => {
                info!("{:?}: Read {}bytes", self.socket.peer_addr(), n);
                self.read_buf.extend(&abuf[0..n]);
                Ok(())
            }
        }
    }

    fn write(&mut self) -> Result<(), Error> {
        let n = self
            .socket
            .write(&mut self.write_buf)
            .context("writing buffer")?;
        info!(
            "{:?}: Wrote {} of {} in buffer",
            self.socket.peer_addr(),
            n,
            self.write_buf.len()
        );
        self.write_buf = self.write_buf[n..].to_vec();
        info!(
            "{:?}: Now {:?}b",
            self.socket.peer_addr(),
            self.write_buf.len()
        );
        Ok(())
    }

    fn reregister(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        let mut flags = mio::Ready::readable();
        if !self.write_buf.is_empty() {
            flags.insert(mio::Ready::writable());
        }
        info!("Registering {:?} with {:?}", self, flags);

        event_loop
            .reregister(&self.socket, self.token, flags, mio::PollOpt::oneshot())
            .context("EventLoop#reregister")?;

        Ok(())
    }

    fn enqueue(&mut self, s: &str) {
        self.write_buf.extend(s.as_bytes());
        self.write_buf.push('\n' as u8);
    }
}

#[derive(Debug)]
struct Listener {
    listener: TcpListener,
    sock_status: mio::Ready,
    token: mio::Token,
}

impl Listener {
    fn new(listener: TcpListener, token: mio::Token) -> Listener {
        Listener {
            listener: listener,
            sock_status: mio::Ready::empty(),
            token: token,
        }
    }
    fn reregister(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error> {
        event_loop
            .reregister(
                &self.listener,
                token,
                mio::Ready::readable(),
                mio::PollOpt::edge() | mio::PollOpt::oneshot(),
            ).context("Register listener")?;
        Ok(())
    }
}

impl RuleHandler for Listener {
    fn register(&self, event_loop: &mut mio::Poll, token: mio::Token) -> Result<(), Error> {
        event_loop
            .register(
                &self.listener,
                token,
                mio::Ready::readable(),
                mio::PollOpt::edge() | mio::PollOpt::oneshot(),
            ).context("Register listener")?;
        Ok(())
    }
    fn deregister(&self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        event_loop.deregister(&self.listener)?;
        Ok(())
    }

    fn handle_event(&mut self, _event_loop: &mut mio::Poll, events: mio::Ready) {
        assert!(events.is_readable());
        self.sock_status.insert(events);
        info!(
            "Listener::handle_event: {:?}; this time: {:?}; now: {:?}",
            self.listener.local_addr(),
            events,
            self.sock_status
        );
    }
    fn process_rules(
        &mut self,
        event_loop: &mut mio::Poll,
        to_parent: &mut FnMut(MiChatCommand),
    ) -> Result<(), Error> {
        if self.sock_status.is_readable() {
            info!("the listener socket is ready to accept a connection");
            self.sock_status.remove(mio::Ready::readable());
            let (socket, _client) = self.listener.accept().context("Accept listening socket")?;
            let cmd = MiChatCommand::NewConnection(socket);
            to_parent(cmd);

            self.reregister(event_loop, self.token)?;
        }
        Ok(())
    }

    fn should_close(&self) -> bool {
        false
    }
}

#[derive(Debug)]
enum EventHandler {
    Listener(Listener),
    Conn(Connection),
}

impl ops::Deref for EventHandler {
    type Target = RuleHandler;
    fn deref(&self) -> &Self::Target {
        match self {
            &EventHandler::Conn(ref conn) => conn,
            &EventHandler::Listener(ref listener) => listener,
        }
    }
}
impl ops::DerefMut for EventHandler {
    fn deref_mut(&mut self) -> &mut Self::Target {
        match self {
            &mut EventHandler::Conn(ref mut conn) => conn,
            &mut EventHandler::Listener(ref mut listener) => listener,
        }
    }
}

impl MiChat {
    fn ready(&mut self, event_loop: &mut mio::Poll, token: mio::Token, events: mio::Ready) {
        info!("{:?}: {:?}", token, events);
        self.connections[token.into()].handle_event(event_loop, events);
    }

    fn process(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        let mut parent_actions = VecDeque::new();
        let mut failed = Vec::new();
        loop {
            let mut something_done = false;
            for (idx, conn) in self.connections.iter_mut() {
                if let Err(e) = conn.process_rules(event_loop, &mut |action| {
                    parent_actions.push_back((idx, action))
                }) {
                    failed.push(idx);
                    error!("Error on connection {:?}; Dropping: {:?}", idx, e);
                }

                if conn.should_close() {
                    failed.push(idx);
                    info!("Removing; {:?}", idx);
                }
            }
            for idx in failed.drain(..) {
                let conn = self.connections.remove(idx);
                conn.deregister(event_loop)?;
            }
            for (src, action) in parent_actions.drain(..) {
                something_done = true;
                if let Err(e) = self.process_action(src, action, event_loop) {
                    failed.push(src);
                    error!("Error on action for {:?}; Dropping: {:?}", src, e);
                }
            }
            // If we didn't do anything, we're done.
            if !something_done {
                break;
            }
        }

        Ok(())
    }

    fn run(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        loop {
            self.run_once(event_loop)?;
        }
    }
    fn run_once(&mut self, event_loop: &mut mio::Poll) -> Result<(), Error> {
        let mut events = mio::Events::with_capacity(1024);
        event_loop.poll(&mut events, None)?;
        for ev in &events {
            self.ready(event_loop, ev.token(), ev.readiness())
        }

        self.process(event_loop)
    }
}

fn main() {
    env_logger::init();
    let matches = App::new("michat")
        .arg(
            Arg::with_name("bind")
                .short("l")
                .takes_value(true)
                .required(true),
        ).get_matches();

    let address = value_t_or_exit!(matches.value_of("bind"), std::net::SocketAddr);
    let listener = TcpListener::bind(&address).expect("bind");

    let mut event_loop = mio::Poll::new().expect("Create event loop");
    let mut service = MiChat::new();

    service
        .listen(&mut event_loop, listener)
        .expect("Starting listener");
    info!("running michat listener at: {:?}", address);
    service.run(&mut event_loop).expect("run");
}
<|endoftext|>


<commit_before>#![feature(plugin, custom_derive)]
#![plugin(rocket_codegen)]
#![recursion_limit = "1024"]

#[macro_use] extern crate error_chain;
extern crate rocket;
#[macro_use] extern crate rocket_contrib;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate clap;
#[macro_use] extern crate log;
extern crate env_logger;
extern crate chrono;
extern crate hex;
extern crate uuid;
extern crate r2d2;
extern crate r2d2_postgres;
extern crate postgres;
extern crate migrant_lib;

mod service;
mod handlers;

use std::env;
use clap::{Arg, App, SubCommand};

mod errors {
    use super::*;
    error_chain! {
        foreign_links {
            LogInit(log::SetLoggerError) #[doc = "Error initializing env_logger"];
            ParseInt(std::num::ParseIntError);
            RocketConfig(rocket::config::ConfigError) #[doc = "Error finalizing rocket config"];
        }
    }
}
use errors::*;

static APPNAME: &'static str = "Transfer";

fn run() -> Result<()> {
    let matches = App::new(APPNAME)
        .version(crate_version!())
        .about("Secure Transfer Sever")
        .subcommand(SubCommand::with_name("serve")
                    .about("Initialize Server")
                    .arg(Arg::with_name("port")
                         .long("port")
                         .short("p")
                         .takes_value(true)
                         .help("Port to listen on. Defaults to 3000"))
                    .arg(Arg::with_name("public")
                         .long("public")
                         .help("Serve on '0.0.0.0' instead of 'localhost'"))
                    .arg(Arg::with_name("log")
                         .long("log")
                         .help("Output logging info. Shortcut for settings env-var LOG=info"))
                    .arg(Arg::with_name("workers")
                         .long("workers")
                         .short("w")
                         .takes_value(true)
                         .help("Number of workers to use")))
        .get_matches();

    if let Some(serve_matches) = matches.subcommand_matches("serve") {
        let log = serve_matches.is_present("log");
        if log {
            env::set_var("LOG", "info");
        }
        let port = serve_matches.value_of("port").unwrap_or("3000").parse::<u16>().chain_err(|| "`--port` expects an integer")?;
        let host = if serve_matches.is_present("public") { "0.0.0.0" } else { "localhost" };
        let workers = serve_matches.value_of("workers").unwrap_or("0").parse::<u16>().chain_err(|| "`--workers` expects an integer")?;
        service::start(&host, port, workers, log)?;
        return Ok(());
    }

    eprintln!("{}: see `--help`", APPNAME);
    Ok(())
}

quick_main!(run);
<commit_msg>update logging options<commit_after>#![feature(plugin, custom_derive)]
#![plugin(rocket_codegen)]
#![recursion_limit = "1024"]

#[macro_use] extern crate error_chain;
extern crate rocket;
#[macro_use] extern crate rocket_contrib;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate clap;
#[macro_use] extern crate log;
extern crate env_logger;
extern crate chrono;
extern crate hex;
extern crate uuid;
extern crate r2d2;
extern crate r2d2_postgres;
extern crate postgres;
extern crate migrant_lib;

mod service;
mod handlers;

use std::env;
use clap::{Arg, App, SubCommand};

mod errors {
    use super::*;
    error_chain! {
        foreign_links {
            LogInit(log::SetLoggerError) #[doc = "Error initializing env_logger"];
            ParseInt(std::num::ParseIntError);
            RocketConfig(rocket::config::ConfigError) #[doc = "Error finalizing rocket config"];
        }
    }
}
use errors::*;

static APPNAME: &'static str = "Transfer";

fn run() -> Result<()> {
    let matches = App::new(APPNAME)
        .version(crate_version!())
        .about("Secure Transfer Sever")
        .subcommand(SubCommand::with_name("serve")
                    .about("Initialize Server")
                    .arg(Arg::with_name("port")
                         .long("port")
                         .short("p")
                         .takes_value(true)
                         .help("Port to listen on. Defaults to 3000"))
                    .arg(Arg::with_name("public")
                         .long("public")
                         .help("Serve on '0.0.0.0' instead of 'localhost'"))
                    .arg(Arg::with_name("log")
                         .long("log")
                         .help("Output logging info. Shortcut for setting env-var LOG=info"))
                    .arg(Arg::with_name("debug")
                         .long("debug")
                         .help("Output debug logging info. Shortcut for setting env-var LOG=debug"))
                    .arg(Arg::with_name("workers")
                         .long("workers")
                         .short("w")
                         .takes_value(true)
                         .help("Number of workers to use")))
        .get_matches();

    if let Some(serve_matches) = matches.subcommand_matches("serve") {
        let log_info = serve_matches.is_present("log");
        let log_debug = serve_matches.is_present("debug");
        if log_info { env::set_var("LOG", "info"); }
        if log_debug { env::set_var("LOG", "debug"); }
        let log = if log_info || log_debug { true } else { false };
        let port = serve_matches.value_of("port").unwrap_or("3000").parse::<u16>().chain_err(|| "`--port` expects an integer")?;
        let host = if serve_matches.is_present("public") { "0.0.0.0" } else { "localhost" };
        let workers = serve_matches.value_of("workers").unwrap_or("0").parse::<u16>().chain_err(|| "`--workers` expects an integer")?;
        service::start(&host, port, workers, log)?;
        return Ok(());
    }

    eprintln!("{}: see `--help`", APPNAME);
    Ok(())
}

quick_main!(run);
<|endoftext|>


<commit_before>#![allow(unstable)]

extern crate getopts;
extern crate selecta;

use getopts::{optopt,getopts};
use selecta::configuration::Configuration;
use selecta::search::Search;
use selecta::tty::TTY;
use selecta::tty::IO;
use selecta::screen::Screen;

fn main() {
    let initial_query = extract_initial_query();
    let lines = read_lines();

    let config = Configuration::from_inputs(lines, initial_query, Some(20));
    let mut search = Search::blank(config);

    let mut tty = TTY::new();
    let mut screen = Screen::new();

    screen.print(&search);

    while !search.is_done() {
        let input = tty.read();
        match input {
            Some(n) => {
                search = screen.handle_keystroke(search, n.as_slice());
            },
            None => break,
        };
        screen.print(&search);
    }
    match search.selection {
        Some(ref t) => println!("{}\n", t),
        None => println!("None"),
    };
    screen.ansi.show_cursor();
}

fn extract_initial_query() -> Option<String> {
    let args: Vec<String> = std::os::args();
    let opts = &[
        optopt("s", "search", "initial search query", ""),
    ];
    let matches = getopts(args.tail(), opts).unwrap();

    matches.opt_str("s")
}

fn read_lines() -> Vec<String> {
    let mut lines: Vec<String> = Vec::new();
    let mut reader = std::io::stdio::stdin();

    loop {
        match reader.read_line() {
            Err(_) => break,
            Ok(l) => {
                let message = l.trim();
                lines.push(message.to_string());
            },
        };
    };
    lines
}
<commit_msg>Read lines in a functional kind of way<commit_after>#![allow(unstable)]

extern crate getopts;
extern crate selecta;

use getopts::{optopt,getopts};
use selecta::configuration::Configuration;
use selecta::search::Search;
use selecta::tty::TTY;
use selecta::tty::IO;
use selecta::screen::Screen;

fn main() {
    let initial_query = extract_initial_query();
    let lines = read_lines();

    let config = Configuration::from_inputs(lines, initial_query, Some(20));
    let mut search = Search::blank(config);

    let mut tty = TTY::new();
    let mut screen = Screen::new();

    screen.print(&search);

    while !search.is_done() {
        let input = tty.read();
        match input {
            Some(n) => {
                search = screen.handle_keystroke(search, n.as_slice());
            },
            None => break,
        };
        screen.print(&search);
    }
    match search.selection {
        Some(ref t) => println!("{}\n", t),
        None => println!("None"),
    };
    screen.ansi.show_cursor();
}

fn extract_initial_query() -> Option<String> {
    let args: Vec<String> = std::os::args();
    let opts = &[
        optopt("s", "search", "initial search query", ""),
    ];
    let matches = getopts(args.tail(), opts).unwrap();

    matches.opt_str("s")
}

fn read_lines() -> Vec<String> {
    std::io::stdio::stdin().lock().lines().map( |line| {
        line.unwrap().trim().to_string()
    }).collect()
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::io;
use std::io::prelude::*;

#[derive(Debug)]
struct Token {
}

fn tokenize(source: &String) -> Result<Vec<Token>, String> {
    unimplemented!();
}

fn run(source: &String) -> Result<(), String> {
    let tokens = try!(tokenize(source));
    for token in tokens {
        println!("{:?}", token);
    }
    Ok(())
}

fn run_file(file_name: &String) -> Result<(), String> {
    match File::open(file_name) {
        Err(_) => {
            Err("Error opening file".into()) // TODO: add context
        }
        Ok(mut file) => {
            let mut source = String::new();
            match file.read_to_string(&mut source) {
                Err(_) => {
                    Err("Error reading file".into()) // TODO: add context
                }
                Ok(_) => run(&source),
            }
        }
    }
}

fn run_prompt() -> Result<(), String> {
    loop {
        print!("> ");
        io::stdout().flush();
        let mut source = String::new();
        io::stdin().read_line(&mut source);
        try!(run(&source));
        ()
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let result = match args.len() {
        // The first argument is the program name
        1 => run_prompt(),
        2 => run_file(&args[1]),
        _ => {
            println!("Usage: rulox [script]");
            Ok(())
        }
    };
    let exit_code = match result {
        Ok(_) => 0,
        Err(e) => {
            println!("{}", e);
            1
        }
    };
    std::process::exit(exit_code)
}
<commit_msg>enum with all tokens<commit_after>use std::env;
use std::fs::File;
use std::io;
use std::io::prelude::*;

#[derive(Debug)]
enum Token {
    LeftParen,
    RightParen,
    LeftBrace,
    RightBrace,
    Comma,
    Dot,
    Minus,
    Plus,
    Semicolon,
    Slash,
    Star,
    Bang,
    BangEqual,
    Greater,
    GreaterEqual,
    Less,
    LessEqual,
    Identifier(String),
    StringLiteral(String),
    NumberLiteral(u32),
    // Keywords
    And,
    Class,
    Else,
    False,
    Fun,
    For,
    If,
    Nil,
    Or,
    Print,
    Return,
    Super,
    This,
    True,
    Var,
    While,

    Eof
}

fn tokenize(source: &String) -> Result<Vec<Token>, String> {
    unimplemented!();
}

fn run(source: &String) -> Result<(), String> {
    let tokens = try!(tokenize(source));
    for token in tokens {
        println!("{:?}", token);
    }
    Ok(())
}

fn run_file(file_name: &String) -> Result<(), String> {
    match File::open(file_name) {
        Err(_) => {
            Err("Error opening file".into()) // TODO: add context
        }
        Ok(mut file) => {
            let mut source = String::new();
            match file.read_to_string(&mut source) {
                Err(_) => {
                    Err("Error reading file".into()) // TODO: add context
                }
                Ok(_) => run(&source),
            }
        }
    }
}

fn run_prompt() -> Result<(), String> {
    loop {
        print!("> ");
        io::stdout().flush();
        let mut source = String::new();
        io::stdin().read_line(&mut source);
        try!(run(&source));
        ()
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let result = match args.len() {
        // The first argument is the program name
        1 => run_prompt(),
        2 => run_file(&args[1]),
        _ => {
            println!("Usage: rulox [script]");
            Ok(())
        }
    };
    let exit_code = match result {
        Ok(_) => 0,
        Err(e) => {
            println!("{}", e);
            1
        }
    };
    std::process::exit(exit_code)
}
<|endoftext|>