<commit_before>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;
extern crate serde_json;
#[macro_use] extern crate lazy_static;
extern crate rocket_contrib;
#[macro_use] extern crate serde_derive;
extern crate serde;
extern crate derbyjson;

use rocket::response::*;
use rocket_contrib::JSON;

use std::collections::HashMap;
use std::thread;
use std::time::Duration;
use std::ffi::OsStr;

mod gamestate;
mod jamstate;
mod clock;
mod roster;
mod penaltycodes;

use gamestate::{Penalty, ActiveClock};
use jamstate::Team;
#[get("/")]
fn index() -> &'static str {
    "Hello, world!"
}

#[derive(Deserialize)]
struct PenaltyCmd {
    skater: String,
    code: char,
}

#[post("/penalties/<team>", format = "application/json", data = "<cmd>")]
fn add_penalty(team: Team, cmd: JSON<PenaltyCmd>) -> JSON<HashMap<String, Vec<Penalty>>> {
    let mut game = gamestate::get_game_mut();
    game.penalty(team, cmd.skater.as_str(), cmd.code);
    JSON(game.team_penalties(team))
}

#[get("/penalties/<team>")]
fn get_penalties(team: Team) -> JSON<HashMap<String, Vec<Penalty>>>
{
    let game = gamestate::get_game();
    JSON(game.team_penalties(team))
}

#[derive(Serialize)]
struct ScoreUpdate {
    score: (u32, u32),
    jamscore: (u32, u32),
    gameclock: (u8, Duration),
    activeclock: ActiveClock,
    timeouts: (u8, u8),
    reviews: (u8, u8),
}

#[get("/score/update")]
fn scoreupdate() -> JSON<ScoreUpdate> {
    let game = gamestate::get_game();
    let cur_jam = game.cur_jam();
    let jamscore = if cur_jam.starttime.is_some() {
        cur_jam.jam_score()
    } else {
        match game.prev_jam() {
            Some(ref prev_jam) => prev_jam.jam_score(),
            None => (0, 0)
        }
    };

    JSON(ScoreUpdate {
        score: game.total_score(), jamscore: jamscore,
        gameclock: game.get_time(), activeclock: game.get_active_clock(),
        reviews: game.reviews(), timeouts: game.timeouts(),
    })
}

#[allow(non_camel_case_types)]
#[derive(Deserialize)]
enum UpdateCommand {
    score_adj(i8, i8),
    //score_set(i8, i8),
    set_time(u16),
    start_jam,
    stop_jam,
    team_timeout(Team),
    star_pass(Team),
    official_timeout,
    official_review(Team),
    review_lost(Team),
    review_retained(Team),
}

#[post("/score/update", format = "application/json", data = "<cmd>")]
fn post_score(cmd: JSON<UpdateCommand>) -> &'static str
{
    let mut game = gamestate::get_game_mut();
    match cmd.0 {
        UpdateCommand::score_adj(a1, a2) =>
            game.cur_jam_mut().adj_score(a1, a2),
        UpdateCommand::start_jam => {
            println!("Jam On!");
            game.start_jam();
        },
        UpdateCommand::stop_jam => {
            println!("Jam Off!");
            game.stop_jam();
        },
        UpdateCommand::official_timeout => {
            game.official_timeout();
        },
        UpdateCommand::team_timeout(team) => {
            game.team_timeout(team);
        },
        UpdateCommand::star_pass(team) => {
            game.cur_jam_mut()[team].pass_star();
        },
        UpdateCommand::set_time(secs) => {
            game.set_time(Duration::new(secs as u64, 0));
        }
        _ => {}
    };
    "success"
}

#[get("/score")]
fn scoreboard() -> content::HTML<&'static str> {
    content::HTML(include_str!("scoreboard.html"))
}

#[get("/scoreboard.js")]
fn scoreboardjs() -> &'static str { include_str!("scoreboard.js") }

#[get("/penalties")]
fn penalties() -> content::HTML<&'static str> {
    content::HTML(include_str!("penalties.html"))
}

#[get("/penalties.js")]
fn penaltiesjs() -> &'static str { include_str!("penalties.js") }

#[get("/mobilejt.js")]
fn mobilejtjs() -> &'static str { include_str!("mobilejt.js") }

#[get("/mobilejt")]
fn mobilejt() -> content::HTML<&'static str> {
    content::HTML(include_str!("mobilejt.html"))
}

#[get("/gameroster/<team>")]
fn gameroster(team: Team) -> JSON<roster::Team> {
    let game = gamestate::get_game();
    let skaters = game.roster(team);
    JSON(skaters.clone()) // ew. Why can't we serialize a ref?
}

fn main() {
    let rosters = roster::load_rosters(OsStr::new("rosters")).unwrap_or(Vec::new());
    println!("Loaded {} rosters", rosters.len());
    gamestate::start_game(&rosters[0], &rosters[1]);
    thread::spawn(move || {
        loop {
            thread::park_timeout(Duration::new(0, 100_000_000));
            gamestate::get_game_mut().tick();
        }
    });

    rocket::ignite().mount("/", routes![index,  gameroster,
                                        penalties, penaltiesjs, get_penalties,
                                        scoreboard, scoreboardjs,
                                        mobilejt, mobilejtjs,
                                        scoreupdate, post_score, add_penalty]).launch();
}
<commit_msg>Compactify post_score() a bit<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;
extern crate serde_json;
#[macro_use] extern crate lazy_static;
extern crate rocket_contrib;
#[macro_use] extern crate serde_derive;
extern crate serde;
extern crate derbyjson;

use rocket::response::*;
use rocket_contrib::JSON;

use std::collections::HashMap;
use std::thread;
use std::time::Duration;
use std::ffi::OsStr;

mod gamestate;
mod jamstate;
mod clock;
mod roster;
mod penaltycodes;

use gamestate::{Penalty, ActiveClock};
use jamstate::Team;
#[get("/")]
fn index() -> &'static str {
    "Hello, world!"
}

#[derive(Deserialize)]
struct PenaltyCmd {
    skater: String,
    code: char,
}

#[post("/penalties/<team>", format = "application/json", data = "<cmd>")]
fn add_penalty(team: Team, cmd: JSON<PenaltyCmd>) -> JSON<HashMap<String, Vec<Penalty>>> {
    let mut game = gamestate::get_game_mut();
    game.penalty(team, cmd.skater.as_str(), cmd.code);
    JSON(game.team_penalties(team))
}

#[get("/penalties/<team>")]
fn get_penalties(team: Team) -> JSON<HashMap<String, Vec<Penalty>>>
{
    let game = gamestate::get_game();
    JSON(game.team_penalties(team))
}

#[derive(Serialize)]
struct ScoreUpdate {
    score: (u32, u32),
    jamscore: (u32, u32),
    gameclock: (u8, Duration),
    activeclock: ActiveClock,
    timeouts: (u8, u8),
    reviews: (u8, u8),
}

#[get("/score/update")]
fn scoreupdate() -> JSON<ScoreUpdate> {
    let game = gamestate::get_game();
    let cur_jam = game.cur_jam();
    let jamscore = if cur_jam.starttime.is_some() {
        cur_jam.jam_score()
    } else {
        match game.prev_jam() {
            Some(ref prev_jam) => prev_jam.jam_score(),
            None => (0, 0)
        }
    };

    JSON(ScoreUpdate {
        score: game.total_score(), jamscore: jamscore,
        gameclock: game.get_time(), activeclock: game.get_active_clock(),
        reviews: game.reviews(), timeouts: game.timeouts(),
    })
}

#[allow(non_camel_case_types)]
#[derive(Deserialize)]
enum UpdateCommand {
    score_adj(i8, i8),
    //score_set(i8, i8),
    set_time(u16),
    start_jam,
    stop_jam,
    team_timeout(Team),
    star_pass(Team),
    official_timeout,
    official_review(Team),
    review_lost(Team),
    review_retained(Team),
}

#[post("/score/update", format = "application/json", data = "<cmd>")]
fn post_score(cmd: JSON<UpdateCommand>) -> &'static str
{
    let mut game = gamestate::get_game_mut();
    match cmd.0 {
        UpdateCommand::score_adj(a1, a2) =>
            game.cur_jam_mut().adj_score(a1, a2),
        UpdateCommand::start_jam => game.start_jam(),
        UpdateCommand::stop_jam => game.stop_jam(),
        UpdateCommand::official_timeout => game.official_timeout(),
        UpdateCommand::team_timeout(team) => { game.team_timeout(team); },
        UpdateCommand::star_pass(team) =>
            game.cur_jam_mut()[team].pass_star(),
        UpdateCommand::set_time(secs) =>
            game.set_time(Duration::new(secs as u64, 0)),
        _ => {}
    };
    "success"
}

#[get("/score")]
fn scoreboard() -> content::HTML<&'static str> {
    content::HTML(include_str!("scoreboard.html"))
}

#[get("/scoreboard.js")]
fn scoreboardjs() -> &'static str { include_str!("scoreboard.js") }

#[get("/penalties")]
fn penalties() -> content::HTML<&'static str> {
    content::HTML(include_str!("penalties.html"))
}

#[get("/penalties.js")]
fn penaltiesjs() -> &'static str { include_str!("penalties.js") }

#[get("/mobilejt.js")]
fn mobilejtjs() -> &'static str { include_str!("mobilejt.js") }

#[get("/mobilejt")]
fn mobilejt() -> content::HTML<&'static str> {
    content::HTML(include_str!("mobilejt.html"))
}

#[get("/gameroster/<team>")]
fn gameroster(team: Team) -> JSON<roster::Team> {
    let game = gamestate::get_game();
    let skaters = game.roster(team);
    JSON(skaters.clone()) // ew. Why can't we serialize a ref?
}

fn main() {
    let rosters = roster::load_rosters(OsStr::new("rosters")).unwrap_or(Vec::new());
    println!("Loaded {} rosters", rosters.len());
    gamestate::start_game(&rosters[0], &rosters[1]);
    thread::spawn(move || {
        loop {
            thread::park_timeout(Duration::new(0, 100_000_000));
            gamestate::get_game_mut().tick();
        }
    });

    rocket::ignite().mount("/", routes![index,  gameroster,
                                        penalties, penaltiesjs, get_penalties,
                                        scoreboard, scoreboardjs,
                                        mobilejt, mobilejtjs,
                                        scoreupdate, post_score, add_penalty]).launch();
}
<|endoftext|>


<commit_before>extern crate count;

extern crate clap;
extern crate walkdir;
extern crate itertools;

use clap::{Arg, App, AppSettings};
use walkdir::WalkDir;

use std::collections::HashMap;
use std::collections::hash_map::Entry;

use count as c;

fn main() {

    let matches = App::new("count")
        .global_settings(&[AppSettings::ColoredHelp])
        .version("0.1")
        .author("Curtis Gagliardi <curtis@curtis.io>")
        .about("counts things quickly hopefully")
        .arg(Arg::with_name("exclude")
            .required(false)
            .long("exclude")
            .value_name("FILES/DIRS")
            .takes_value(true)
            .value_delimiter(",")
            .help("comma separated list of files/directories to ignore"))
        .arg(Arg::with_name("target")
            .required(true)
            .help("The file or directory to count lines in/of"))
        .get_matches();

    let filepaths = matches.values_of("target").unwrap();

    let mut counts: Vec<(c::Lang, String, c::Count)> = Vec::new();
    for filepath in filepaths {
        for entry in WalkDir::new(filepath) {
            let entry = match entry {
                Ok(e) => e,
                Err(_) => {
                    continue;
                }
            };

            if entry.file_type().is_file() {
                let path = entry.path().to_str().unwrap();
                let lang = c::lang_from_ext(path);
                if lang != c::Lang::Unrecognized {
                    let count = c::count(path);
                    counts.push((lang, String::from(path), count));
                }
            }
        }
    }

    let mut lang_counts_by_file: HashMap<c::Lang, Vec<(String, c::Count)>> = HashMap::new();
    for (lang, filepath, count) in counts {
        match lang_counts_by_file.entry(lang) {
            Entry::Occupied(mut lang_counts_by_file) => {
                lang_counts_by_file.get_mut().push((filepath, count))
            }
            Entry::Vacant(lang_counts_by_file) => {
                lang_counts_by_file.insert(vec![(filepath, count)]);
            }
        };
    }

    let mut lang_totals: HashMap<&c::Lang, c::LangTotal> = HashMap::new();
    for (lang, count_vec) in &lang_counts_by_file {
        // TODO(cgag): use a fold?
        let mut lang_total: c::Count = Default::default();
        for &(_, ref count) in count_vec.iter() {
            lang_total.merge(count);
        }
        lang_totals.insert(lang,
                           c::LangTotal {
                               files: count_vec.len() as u32,
                               count: lang_total,
                           });
    }

    let mut totals_by_lang = lang_totals.iter().collect::<Vec<(&&c::Lang, &c::LangTotal)>>();
    totals_by_lang.sort_by(|&(_, c1), &(_, c2)| c2.count.code.cmp(&c1.count.code));

    let mut totals = c::LangTotal {
        files: 0,
        count: Default::default(),
    };
    for &(_, total) in &totals_by_lang {
        totals.files += total.files;
        totals.count.code += total.count.code;
        totals.count.blank += total.count.blank;
        totals.count.comment += total.count.comment;
        totals.count.lines += total.count.lines;
    }

    println!("-------------------------------------------------------------------------------");
    println!(" {0: <12} {1: >12} {2: >12} {3: >12} {4: >12} {5: >12}",
             "Language",
             "Files",
             "Lines",
             "Blank",
             "Comment",
             "Code");
    println!("-------------------------------------------------------------------------------");

    for &(lang, total) in &totals_by_lang {
        println!(" {0: <12} {1: >12} {2: >12} {3: >12} {4: >12} {5: >12}",
                 lang,
                 total.files,
                 total.count.lines,
                 total.count.blank,
                 total.count.comment,
                 total.count.code);
    }

    println!("-------------------------------------------------------------------------------");
    println!(" {0: <12} {1: >12} {2: >12} {3: >12} {4: >12} {5: >12}",
             "Total",
             totals.files,
             totals.count.lines,
             totals.count.blank,
             totals.count.comment,
             totals.count.code);
    println!("-------------------------------------------------------------------------------");
}
<commit_msg>increase width of language column<commit_after>extern crate count;

extern crate clap;
extern crate walkdir;
extern crate itertools;

use clap::{Arg, App, AppSettings};
use walkdir::WalkDir;

use std::collections::HashMap;
use std::collections::hash_map::Entry;

use count as c;

fn main() {

    let matches = App::new("count")
        .global_settings(&[AppSettings::ColoredHelp])
        .version("0.1")
        .author("Curtis Gagliardi <curtis@curtis.io>")
        .about("counts things quickly hopefully")
        .arg(Arg::with_name("exclude")
            .required(false)
            .long("exclude")
            .value_name("FILES/DIRS")
            .takes_value(true)
            .value_delimiter(",")
            .help("comma separated list of files/directories to ignore"))
        .arg(Arg::with_name("target")
            .required(true)
            .help("The file or directory to count lines in/of"))
        .get_matches();

    let filepaths = matches.values_of("target").unwrap();

    let mut counts: Vec<(c::Lang, String, c::Count)> = Vec::new();
    for filepath in filepaths {
        for entry in WalkDir::new(filepath) {
            let entry = match entry {
                Ok(e) => e,
                Err(_) => {
                    continue;
                }
            };

            if entry.file_type().is_file() {
                let path = entry.path().to_str().unwrap();
                let lang = c::lang_from_ext(path);
                if lang != c::Lang::Unrecognized {
                    let count = c::count(path);
                    counts.push((lang, String::from(path), count));
                }
            }
        }
    }

    let mut lang_counts_by_file: HashMap<c::Lang, Vec<(String, c::Count)>> = HashMap::new();
    for (lang, filepath, count) in counts {
        match lang_counts_by_file.entry(lang) {
            Entry::Occupied(mut lang_counts_by_file) => {
                lang_counts_by_file.get_mut().push((filepath, count))
            }
            Entry::Vacant(lang_counts_by_file) => {
                lang_counts_by_file.insert(vec![(filepath, count)]);
            }
        };
    }

    let mut lang_totals: HashMap<&c::Lang, c::LangTotal> = HashMap::new();
    for (lang, count_vec) in &lang_counts_by_file {
        // TODO(cgag): use a fold?
        let mut lang_total: c::Count = Default::default();
        for &(_, ref count) in count_vec.iter() {
            lang_total.merge(count);
        }
        lang_totals.insert(lang,
                           c::LangTotal {
                               files: count_vec.len() as u32,
                               count: lang_total,
                           });
    }

    let mut totals_by_lang = lang_totals.iter().collect::<Vec<(&&c::Lang, &c::LangTotal)>>();
    totals_by_lang.sort_by(|&(_, c1), &(_, c2)| c2.count.code.cmp(&c1.count.code));

    let mut totals = c::LangTotal {
        files: 0,
        count: Default::default(),
    };
    for &(_, total) in &totals_by_lang {
        totals.files += total.files;
        totals.count.code += total.count.code;
        totals.count.blank += total.count.blank;
        totals.count.comment += total.count.comment;
        totals.count.lines += total.count.lines;
    }

    let linesep = "---------------------------------------------------------------------------------";

    println!("{}", linesep);
    println!(" {0: <18} {1: >8} {2: >12} {3: >12} {4: >12} {5: >12}",
             "Language",
             "Files",
             "Lines",
             "Blank",
             "Comment",
             "Code");
    println!("{}", linesep);

    for &(lang, total) in &totals_by_lang {
        println!(" {0: <18} {1: >8} {2: >12} {3: >12} {4: >12} {5: >12}",
                 lang,
                 total.files,
                 total.count.lines,
                 total.count.blank,
                 total.count.comment,
                 total.count.code);
    }

    println!("{}", linesep);
    println!(" {0: <18} {1: >8} {2: >12} {3: >12} {4: >12} {5: >12}",
             "Total",
             totals.files,
             totals.count.lines,
             totals.count.blank,
             totals.count.comment,
             totals.count.code);
    println!("{}", linesep);
}
<|endoftext|>


<commit_before>/*
* rust-clean - Copyright (c) 2014 Gomez Guillaume.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim
*    that you wrote the original software. If you use this software in a product,
*    an acknowledgment in the product documentation would be appreciated but is
*    not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
*    misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/

use std::io::fs;
use std::os;
use std::path::posix::Path;

struct CleanOptions {
    recursive: bool,
    verbose: bool,
    confirmation: bool
}

fn ask_confirmation(file: &Path) -> bool {
    loop {
        print!("clean: remove \x1b[37;1m'{}'\x1b[0m (y/n) ? ", file.as_str().unwrap());
        match std::io::stdio::stdin().read_line() {
            Ok(s) => {
                let tmp_s = s.replace("\r\n", "").replace("\n", "");

                if tmp_s.as_slice() == "y" || tmp_s.as_slice() == "yes" {
                    return true;
                } else if tmp_s.as_slice() == "n" || tmp_s.as_slice() == "no" {
                    return false;
                }
            }
            Err(_) => {}
        }
    }
}

fn start_clean(options: &CleanOptions, entry: &Path) {
    if entry.exists() {
        if entry.is_dir() {
            if options.recursive || entry.as_str().unwrap() == "." {
                match fs::readdir(entry) {
                    Ok(res) => {
                        if options.verbose {
                            println!("\x1b[36;1m-> Entering {}\x1b[0m", entry.as_str().unwrap());
                        }
                        for tmp in res.iter() {
                            start_clean(options, tmp);
                        }
                        if options.verbose {
                            println!("\x1b[34;1m<- Leaving {}\x1b[0m", entry.as_str().unwrap());
                        }
                    }
                    Err(e) => {
                        println!("\x1b[31;1mProblem with this directory: {} -> {}\x1b[0m", entry.as_str().unwrap(), e);
                    }
                }
            }
        } else {
            match entry.filename() {
                Some(s) => {
                    if s.last().unwrap() == &('~' as u8) {
                        if !options.confirmation || ask_confirmation(&Path::new(s)) {
                            match fs::unlink(entry) {
                                Ok(_) => {
                                    if options.verbose {
                                        println!("\x1b[32;1m{} deleted\x1b[0m", entry.as_str().unwrap());
                                    }
                                }
                                Err(e) => {
                                    println!("\x1b[31;1mProblem with this file: {} -> {}\x1b[0m", entry.as_str().unwrap(), e);
                                }
                            }
                        }
                    }
                }
                None => {
                    println!("\x1b[31;1mProblem with this file: {}\x1b[0m", entry.as_str().unwrap());
                }
            }
        }
    } else {
        println!("\x1b[31;1mProblem with this entry: {}\x1b[0m", entry.as_str().unwrap());
    }
}

fn print_help() {
    println!("./clean [options] [files | dirs]");
    println!("    -r : recursive mode");
    println!("    -v : verbose mode");
    println!("    -i : prompt before every removal");
    println!("--help : print this help");
}

fn main() {
    let mut args = os::args().clone();
    let mut options = CleanOptions{recursive: false, verbose: false, confirmation: false};
    let mut files = Vec::new();

    args.remove(0);
    for tmp in args.iter() {
        if tmp.clone().into_bytes()[0] == '-' as u8 {
            let mut tmp_arg = String::from_str(tmp.as_slice());

            tmp_arg.shift_char();
            if tmp_arg.len() > 0 {
                for character in tmp_arg.into_bytes().iter() {
                    match *character as char {
                        '-' => {
                            if tmp.as_slice() == "--help" {
                                print_help();
                                return;
                            }
                        }
                        'r' => {
                            options.recursive = true;
                        }
                        'v' => {
                            options.verbose = true;
                        }
                        'i' => {
                            options.confirmation = true;
                        }
                        _ => {
                            fail!("Unknown option: '{}', to have the options list, please launch with '-h' option\n", character);
                        }
                    }
                }
            } else {
                files.push(Path::new(tmp.as_slice()));
            }
        }
    }
    if files.len() == 0 {
        files.push(Path::new(String::from_str(".").as_slice()));
    }
    if options.verbose {
        println!("\x1b[33;1m=== VERBOSE MODE ===\x1b[0m");
    }
    for tmp in files.iter() {
        start_clean(&options, tmp);
    }
    if options.verbose {
        println!("\x1b[33;1mEnd of execution\x1b[0m");
    }
}<commit_msg>Update to last rust compiler version<commit_after>/*
* rust-clean - Copyright (c) 2014 Gomez Guillaume.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim
*    that you wrote the original software. If you use this software in a product,
*    an acknowledgment in the product documentation would be appreciated but is
*    not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
*    misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/

use std::io::fs;
use std::os;
use std::path::posix::Path;
use std::io::fs::PathExtensions;

struct CleanOptions {
    recursive: bool,
    verbose: bool,
    confirmation: bool
}

fn ask_confirmation(file: &Path) -> bool {
    loop {
        print!("clean: remove \x1b[37;1m'{}'\x1b[0m (y/n) ? ", file.as_str().unwrap());
        match std::io::stdio::stdin().read_line() {
            Ok(s) => {
                let tmp_s = s.replace("\r\n", "").replace("\n", "");

                if tmp_s.as_slice() == "y" || tmp_s.as_slice() == "yes" {
                    return true;
                } else if tmp_s.as_slice() == "n" || tmp_s.as_slice() == "no" {
                    return false;
                }
            }
            Err(_) => {}
        }
    }
}

fn start_clean(options: &CleanOptions, entry: &Path) {
    if entry.exists() {
        if entry.is_dir() {
            if options.recursive || entry.as_str().unwrap() == "." {
                match fs::readdir(entry) {
                    Ok(res) => {
                        if options.verbose {
                            println!("\x1b[36;1m-> Entering {}\x1b[0m", entry.as_str().unwrap());
                        }
                        for tmp in res.iter() {
                            start_clean(options, tmp);
                        }
                        if options.verbose {
                            println!("\x1b[34;1m<- Leaving {}\x1b[0m", entry.as_str().unwrap());
                        }
                    }
                    Err(e) => {
                        println!("\x1b[31;1mProblem with this directory: {} -> {}\x1b[0m", entry.as_str().unwrap(), e);
                    }
                }
            }
        } else {
            match entry.filename() {
                Some(s) => {
                    if s.last().unwrap() == &('~' as u8) {
                        if !options.confirmation || ask_confirmation(&Path::new(s)) {
                            match fs::unlink(entry) {
                                Ok(_) => {
                                    if options.verbose {
                                        println!("\x1b[32;1m{} deleted\x1b[0m", entry.as_str().unwrap());
                                    }
                                }
                                Err(e) => {
                                    println!("\x1b[31;1mProblem with this file: {} -> {}\x1b[0m", entry.as_str().unwrap(), e);
                                }
                            }
                        }
                    }
                }
                None => {
                    println!("\x1b[31;1mProblem with this file: {}\x1b[0m", entry.as_str().unwrap());
                }
            }
        }
    } else {
        println!("\x1b[31;1mProblem with this entry: {}\x1b[0m", entry.as_str().unwrap());
    }
}

fn print_help() {
    println!("./clean [options] [files | dirs]");
    println!("    -r : recursive mode");
    println!("    -v : verbose mode");
    println!("    -i : prompt before every removal");
    println!("--help : print this help");
}

fn main() {
    let mut args = os::args().clone();
    let mut options = CleanOptions{recursive: false, verbose: false, confirmation: false};
    let mut files = Vec::new();

    args.remove(0);
    for tmp in args.iter() {
        if tmp.clone().into_bytes()[0] == '-' as u8 {
            let mut tmp_arg = String::from_str(tmp.as_slice());

            tmp_arg.remove(0);
            if tmp_arg.len() > 0 {
                for character in tmp_arg.into_bytes().iter() {
                    match *character as char {
                        '-' => {
                            if tmp.as_slice() == "--help" {
                                print_help();
                                return;
                            }
                        }
                        'r' => {
                            options.recursive = true;
                        }
                        'v' => {
                            options.verbose = true;
                        }
                        'i' => {
                            options.confirmation = true;
                        }
                        _ => {
                            fail!("Unknown option: '{}', to have the options list, please launch with '-h' option\n", character);
                        }
                    }
                }
            } else {
                files.push(Path::new(tmp.as_slice()));
            }
        }
    }
    if files.len() == 0 {
        files.push(Path::new(String::from_str(".").as_slice()));
    }
    if options.verbose {
        println!("\x1b[33;1m=== VERBOSE MODE ===\x1b[0m");
    }
    for tmp in files.iter() {
        start_clean(&options, tmp);
    }
    if options.verbose {
        println!("\x1b[33;1mEnd of execution\x1b[0m");
    }
}<|endoftext|>


<commit_before>

#![feature(path_ext)]
#![feature(convert)]
extern crate mysql;
extern crate toml;
extern crate rustc_serialize;
#[macro_use]
extern crate lazy_static;

mod lib;

use mysql::conn::MyOpts;
use std::default::Default;
use mysql::conn::pool;
use mysql::error::MyError;
use mysql::conn::pool::MyPooledConn;
use mysql::value::from_value;

use std::error::Error;

use toml::Table;
use toml::Value;

use lib::config;
use lib::downloader::DownloadDB;
use lib::downloader::Downloader;
use lib::downloader::DownloadError;
use lib::socket;

static VERSION : &'static str = "0.1"; // String not valid
static SLEEP_MS: u32 = 5000;

lazy_static! {
    static ref CONFIG: config::Config = {
        println!("Starting yayd-backend v{}",&VERSION);
        config::init_config() //return
    };

}

//#[repr(i8)] borken #10292
enum QueryCodes {
    Waiting = 0,
    InProgress = 1,
    Finished = 2,
    Failed = 3,
}

fn main() {
    let opts = mysql_options();
    let pool = match pool::MyPool::new(opts) {
        Ok(conn) => { println!("Connected successfully."); conn},
        Err(err) => panic!("Unable to establish a connection!\n{}",err),
    };
    loop {
        if let Some(result) = request_entry(& pool) {
            if result.playlist {
                println!("Playlist not supported atm!");
                //TODO: set playlist entry to err
            }
            let qid = result.qid.clone();                 //&QueryCodes::InProgress as i32
            set_query_code(&mut pool.get_conn().unwrap(), &1, &result.qid).ok().expect("Failed to set query code!");

            let code = if handle_download(result) {
                2//QueryCodes::Finished as i32
            } else {
                3//QueryCodes::Failed as i32
            };
            set_query_code(&mut pool.get_conn().unwrap(), &code,&qid).ok().expect("Failed to set query code!");
        } else {
            println!("Pausing..");
            std::thread::sleep_ms(SLEEP_MS);
        }
    }

    // let downloader = downloader::Downloader::new(download_db);
    // downloader.download_video();

    println!("EOL!");
}

///Download handler
///Used by the playlist/file handler to download one file
///Based on the quality it needs to download audio & video splitted & convert them together
///In case of a playlist download it depends on the target download folder & if should bezipped
///In case of a DMCA we need to download the file via the socket connector,
///which will output a mp3, or if requested, a hard quality depending on the max-available of
///the video url. Thus in case of a DMCA we can't pick a quality anymore.
///Also the filename depends on the socket output then.
///
///If it's a non-zipped single file, the file is moved after a success download,convert etc to the
///main folder from which it should be downloadable.
///The original non-ascii & url_encode name of the file is stored in the DB
fn handle_download(downl_db: DownloadDB) -> bool{
    let dbcopy = downl_db.clone(); //copy, all implement copy & no &'s in use
    let download = Downloader::new(downl_db);
    //get filename, check for DMCA
    let dmca = false; // "succ." dmca -> file already downloaded
    let name = match download.get_file_name() { // get filename
        Ok(v) => v,
        Err(DownloadError::DMCAError) => { //now request via lib..
            println!("DMCA error!");
            let name = match download.lib_request_video(&dbcopy.url, &CONFIG.general.jar_folder, &CONFIG.general.jar_cmd) {
                Err(err) => { println!("Offliberty-call error {:?}", err); return false; },
                Ok(v) => { dmca = true; v },
            }
        },
        Err(e) => { // unknown error / video private etc.. abort
            println!("Unknown error: {:?}", e);
            //TODO: add error descr (change enum etc)
            set_query_state(&dbcopy.pool.clone(),&dbcopy.qid, "Error!");
            return false;
        },
    };
    println!("Filename: {}", name);

    if is_split_container(&dbcopy.quality) { // download both files if needed & convert together
        //TODO: actual logic
    }
    true
}

///Set the state of the current query, also in dependence of the code, see QueryCodes
fn set_query_state(pool: & pool::MyPool,qid: &i64 , state: &str){ // same here
    let mut conn = pool.get_conn().unwrap();
    let mut stmt = conn.prepare("UPDATE querydetails SET status = ? WHERE qid = ?").unwrap();
    let result = stmt.execute(&[&state,qid]); // why is this var needed ?!
    match result {
        Ok(_) => (),
        Err(why) => println!("Error setting query state: {}",why),
    }
}

///Return whether the quality is a split container: video only
///as specified in the docs
fn is_split_container(quality &i16){
    141 | 83 | 82 | 84 | 85 => false,
    _ => true,
}

///Request an entry from the DB that should be handled
fn request_entry(pool: & pool::MyPool) -> Option<DownloadDB> {
    let mut conn = pool.get_conn().unwrap();
    let mut stmt = conn.prepare("SELECT queries.qid,url,type,quality FROM querydetails \
                    INNER JOIN queries \
                    ON querydetails.qid = queries.qid \
                    WHERE querydetails.code = 0 \
                    ORDER BY queries.created \
                    LIMIT 1").unwrap();
    let mut result = stmt.execute(&[]).unwrap();
    let result = match result.next() {
        Some(val) => val.unwrap(),
        None => {return None; },
    };
    println!("Result: {:?}", result[0]);
    println!("result str: {}", result[1].into_str());
    let download_db = DownloadDB { url: from_value::<String>(&result[1]),
                                                quality: from_value::<i16>(&result[3]),
                                                qid: from_value::<i64>(&result[0]),
                                                folder: CONFIG.general.save_dir.clone(),
                                                pool: pool.clone(),
                                                download_limit: CONFIG.general.download_mbps.clone(),
                                                playlist: false, //TEMP
                                                compress: false };
    Some(download_db)
}

fn set_query_code(conn: & mut MyPooledConn, code: &i8, qid: &i64) -> Result<(), DownloadError> { // same here
    let mut stmt = conn.prepare("UPDATE querydetails SET code = ? WHERE qid = ?").unwrap();
    let result = stmt.execute(&[code,qid]); // why is this var needed ?!
    match result {
        Ok(_) => Ok(()),
        Err(why) => Err(DownloadError::DBError(why.description().into())),
    }
}

///Set options for the connection
fn mysql_options() -> MyOpts {
    //let dbconfig = CONFIG.get("db").unwrap().clone();
    //let dbconfig = dbconfig.as_table().unwrap(); // shadow binding to workaround borrow / lifetime problems

    MyOpts {
        tcp_addr: Some(CONFIG.db.ip.clone()),
        tcp_port: CONFIG.db.port,
        user: Some(CONFIG.db.user.clone()),
        pass: Some(CONFIG.db.password.clone()),
        db_name: Some(CONFIG.db.db.clone()),
        ..Default::default() // set other to default
    }
}

///Converts a toml::Value to a Option<String> for mysql::MyOpts
#[allow(deprecated)]
fn get_option_string(table: & Table,key: & str) -> Option<String> {
    let val: Value = table.get(key).unwrap().clone();
    if let toml::Value::String(s) = val {
        Some(s)
    } else { unreachable!() }
}<commit_msg>*plans<commit_after>

#![feature(path_ext)]
#![feature(convert)]
extern crate mysql;
extern crate toml;
extern crate rustc_serialize;
#[macro_use]
extern crate lazy_static;

mod lib;

use mysql::conn::MyOpts;
use std::default::Default;
use mysql::conn::pool;
use mysql::error::MyError;
use mysql::conn::pool::MyPooledConn;
use mysql::value::from_value;

use std::error::Error;

use toml::Table;
use toml::Value;

use lib::config;
use lib::downloader::DownloadDB;
use lib::downloader::Downloader;
use lib::downloader::DownloadError;
use lib::socket;

static VERSION : &'static str = "0.1"; // String not valid
static SLEEP_MS: u32 = 5000;

lazy_static! {
    static ref CONFIG: config::Config = {
        println!("Starting yayd-backend v{}",&VERSION);
        config::init_config() //return
    };

}

//#[repr(i8)] borken #10292
enum QueryCodes {
    Waiting = 0,
    InProgress = 1,
    Finished = 2,
    Failed = 3,
}

fn main() {
    let opts = mysql_options();
    let pool = match pool::MyPool::new(opts) {
        Ok(conn) => { println!("Connected successfully."); conn},
        Err(err) => panic!("Unable to establish a connection!\n{}",err),
    };
    loop {
        if let Some(result) = request_entry(& pool) {
            if result.playlist {
                println!("Playlist not supported atm!");
                //TODO: set playlist entry to err
            }
            let qid = result.qid.clone();                 //&QueryCodes::InProgress as i32
            set_query_code(&mut pool.get_conn().unwrap(), &1, &result.qid).ok().expect("Failed to set query code!");

            let code = if handle_download(result) {
                2//QueryCodes::Finished as i32
            } else {
                3//QueryCodes::Failed as i32
            };
            set_query_code(&mut pool.get_conn().unwrap(), &code,&qid).ok().expect("Failed to set query code!");
        } else {
            println!("Pausing..");
            std::thread::sleep_ms(SLEEP_MS);
        }
    }

    // let downloader = downloader::Downloader::new(download_db);
    // downloader.download_video();

    println!("EOL!");
}

///Download handler
///Used by the playlist/file handler to download one file
///Based on the quality it needs to download audio & video splitted & convert them together
///In case of a playlist download it depends on the target download folder & if should bezipped
///In case of a DMCA we need to download the file via the socket connector,
///which will output a mp3, or if requested, a hard quality depending on the max-available of
///the video url. Thus in case of a DMCA we can't pick a quality anymore.
///Also the filename depends on the socket output then.
///
///If it's a non-zipped single file, the file is moved after a success download,convert etc to the
///main folder from which it should be downloadable.
///The original non-ascii & url_encode name of the file is stored in the DB
fn handle_download(downl_db: DownloadDB) -> bool{
    let dbcopy = downl_db.clone(); //copy, all implement copy & no &'s in use
    let download = Downloader::new(downl_db);
    //get filename, check for DMCA
    let dmca = false; // "succ." dmca -> file already downloaded
    let name = match download.get_file_name() { // get filename
        Ok(v) => v,
        Err(DownloadError::DMCAError) => { //now request via lib..
            println!("DMCA error!");
            let name = match download.lib_request_video(&dbcopy.url, &CONFIG.general.jar_folder, &CONFIG.general.jar_cmd) {
                Err(err) => { println!("Offliberty-call error {:?}", err); return false; },
                Ok(v) => { dmca = true; v },
            }
        },
        Err(e) => { // unknown error / video private etc.. abort
            println!("Unknown error: {:?}", e);
            //TODO: add error descr (change enum etc)
            set_query_state(&dbcopy.pool.clone(),&dbcopy.qid, "Error!");
            return false;
        },
    };
    println!("Filename: {}", name);

    if is_split_container(&dbcopy.quality) { // download both files if needed & convert together
        //TODO: actual logic see descr
    }
    //TODO: check for audio

    //TODO: download file, convert if audio ?!
    true
}

///Set the state of the current query, also in dependence of the code, see QueryCodes
fn set_query_state(pool: & pool::MyPool,qid: &i64 , state: &str){ // same here
    let mut conn = pool.get_conn().unwrap();
    let mut stmt = conn.prepare("UPDATE querydetails SET status = ? WHERE qid = ?").unwrap();
    let result = stmt.execute(&[&state,qid]); // why is this var needed ?!
    match result {
        Ok(_) => (),
        Err(why) => println!("Error setting query state: {}",why),
    }
}

///Return whether the quality is a split container: video only
///as specified in the docs
fn is_split_container(quality &i16){
    141 | 83 | 82 | 84 | 85 => false,
    _ => true,
}

///Request an entry from the DB that should be handled
fn request_entry(pool: & pool::MyPool) -> Option<DownloadDB> {
    let mut conn = pool.get_conn().unwrap();
    let mut stmt = conn.prepare("SELECT queries.qid,url,type,quality FROM querydetails \
                    INNER JOIN queries \
                    ON querydetails.qid = queries.qid \
                    WHERE querydetails.code = 0 \
                    ORDER BY queries.created \
                    LIMIT 1").unwrap();
    let mut result = stmt.execute(&[]).unwrap();
    let result = match result.next() {
        Some(val) => val.unwrap(),
        None => {return None; },
    };
    println!("Result: {:?}", result[0]);
    println!("result str: {}", result[1].into_str());
    let download_db = DownloadDB { url: from_value::<String>(&result[1]),
                                                quality: from_value::<i16>(&result[3]),
                                                qid: from_value::<i64>(&result[0]),
                                                folder: CONFIG.general.save_dir.clone(),
                                                pool: pool.clone(),
                                                download_limit: CONFIG.general.download_mbps.clone(),
                                                playlist: false, //TEMP
                                                compress: false };
    Some(download_db)
}

fn set_query_code(conn: & mut MyPooledConn, code: &i8, qid: &i64) -> Result<(), DownloadError> { // same here
    let mut stmt = conn.prepare("UPDATE querydetails SET code = ? WHERE qid = ?").unwrap();
    let result = stmt.execute(&[code,qid]); // why is this var needed ?!
    match result {
        Ok(_) => Ok(()),
        Err(why) => Err(DownloadError::DBError(why.description().into())),
    }
}

///Set options for the connection
fn mysql_options() -> MyOpts {
    //let dbconfig = CONFIG.get("db").unwrap().clone();
    //let dbconfig = dbconfig.as_table().unwrap(); // shadow binding to workaround borrow / lifetime problems

    MyOpts {
        tcp_addr: Some(CONFIG.db.ip.clone()),
        tcp_port: CONFIG.db.port,
        user: Some(CONFIG.db.user.clone()),
        pass: Some(CONFIG.db.password.clone()),
        db_name: Some(CONFIG.db.db.clone()),
        ..Default::default() // set other to default
    }
}

///Converts a toml::Value to a Option<String> for mysql::MyOpts
#[allow(deprecated)]
fn get_option_string(table: & Table,key: & str) -> Option<String> {
    let val: Value = table.get(key).unwrap().clone();
    if let toml::Value::String(s) = val {
        Some(s)
    } else { unreachable!() }
}<|endoftext|>


<commit_before>#![feature(globs)]

extern crate rdb;
use std::os;
use std::io::{BufferedReader, File};

use rdb::PlainFormatter;

pub fn main() {
    let args = os::args();
    if args.len() == 1 {
        println!("Usage: {} [list of files]", args[0]);
        panic!();
    }

    let file = File::open(&Path::new(args[1].to_string()));
    let mut reader = BufferedReader::new(file);

    let mut formatter = PlainFormatter::new();

    rdb::parse(&mut reader, &mut formatter)
}
<commit_msg>Globbing is now added to Rust by default<commit_after>extern crate rdb;
use std::os;
use std::io::{BufferedReader, File};

use rdb::PlainFormatter;

pub fn main() {
    let args = os::args();
    if args.len() == 1 {
        println!("Usage: {} [list of files]", args[0]);
        panic!();
    }

    let file = File::open(&Path::new(args[1].to_string()));
    let mut reader = BufferedReader::new(file);

    let mut formatter = PlainFormatter::new();

    rdb::parse(&mut reader, &mut formatter)
}
<|endoftext|>


<commit_before>#![feature(env, fs, io, old_io, path)]
use std::fs;
use std::io;
use std::io::ReadExt;
use std::old_io::stdio;
use std::path::Path;

const MEMSIZE: usize = 4096;

enum ParserResult {
    Something(Op),
    Nothing,
    EOF
}

use ParserResult::*;

type Ops = Vec<Op>;
enum Op {
    Add(u8),
    Mov(usize),
    In,
    Out,
    Loop(Ops)
}

use Op::*;

struct State {
    index: usize,
    memory: [u8; MEMSIZE]
}

impl State {
    fn new() -> State {
        State { index: 0, memory: [0; MEMSIZE] }
    }

    fn peek(&self) -> u8 {
        self.memory[self.index % MEMSIZE]
    }

    fn poke(&mut self, value: u8) {
        self.memory[self.index % MEMSIZE] = value;
    }

    fn step(&mut self, op: &Op) {
        match op {
            &Add(i) => { let x = self.peek(); self.poke(x + i); },
            &Mov(n) => self.index += n,
            &In => {
                self.poke(stdio::stdin().read_u8().unwrap());
            },
            &Out => {
                stdio::stdout().write_u8(self.peek()).unwrap();
            },
            &Loop(ref ops) => {
                while self.peek() != 0 {
                    self.run(ops);
                }
            }
        }
    }

    fn run(&mut self, ops: &[Op]) {
        for op in ops {
            self.step(op);
        }
    }
}

#[test]
fn test_state_peek() {
    let mut state = State::new();
    state.memory[state.index] = 23;
    assert_eq!(23, state.peek());
    state.index = 5;
    state.memory[state.index] = 42;
    assert_eq!(42, state.peek());
}

#[test]
fn test_state_poke() {
    let mut state = State::new();
    state.poke(23);
    assert_eq!(23, state.memory[state.index]);
    state.index = 5;
    state.poke(42);
    assert_eq!(42, state.memory[state.index]);
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        let reader = reader(&Path::new(filename));
        let mut chars = reader.chars().peekable();

        let mut ops: Ops = Vec::new();
        loop {
            match parse(&mut chars) {
                Something(op) => ops.push(op),
                EOF => break,
                _ => {}
            }
        }

        optimize(&mut ops);

        State::new().run(&ops);
    }
}

fn optimize(ops: &mut Ops) {
    let mut i = 0;
    while (i + 1) < ops.len() {
        match &vec![&ops[i], &ops[i+1]][..] {
            [&Add(a), &Add(b)] => {
                ops[i] = Add(a + b);
                ops.remove(i + 1);
            },
            [&Mov(a), &Mov(b)] => {
                ops[i] = Mov(a + b);
                ops.remove(i + 1);
            },
            _ => i += 1
        }
    }
}

fn parse<T: io::Read>(mut chars: &mut std::iter::Peekable<io::Chars<T>>) -> ParserResult {
    match chars.next() {
        Some(Ok(c)) => match c {
            '+' => Something(Add(1)),
            '-' => Something(Add(-1)),
            '<' => Something(Mov(-1)),
            '>' => Something(Mov(1)),
            ',' => Something(In),
            '.' => Something(Out),
            '[' => {
                let mut children: Ops = Vec::new();
                while chars.peek() != Some(&Ok(']')) {
                    match parse(&mut chars) {
                        Something(op) => children.push(op),
                        Nothing => {},
                        EOF => panic!()
                    }
                }
                chars.next();
                optimize(&mut children);
                Something(Loop(children))
            },
            _ => Nothing  // other characters
        },
        _ => EOF
    }
}

fn reader(path: &Path) -> io::BufReader<fs::File> {
    io::BufReader::new(fs::File::open(path).unwrap())
}
<commit_msg>refactor: move Op vector into OpStream<commit_after>#![feature(env, fs, io, old_io, path)]
use std::fs;
use std::io;
use std::io::ReadExt;
use std::old_io::stdio;
use std::path::Path;

const MEMSIZE: usize = 4096;

enum ParserResult {
    Something(Op),
    Nothing,
    EOF
}

use ParserResult::*;

#[derive(Debug)]
enum Op {
    Add(u8),
    Mov(usize),
    In,
    Out,
    Loop(OpStream)
}

use Op::*;

#[derive(Debug)]
struct OpStream {
    ops: Vec<Op>
}

impl OpStream {
    fn add(&mut self, op: Op) {
        self.ops.push(op);
    }

    fn optimize(&mut self) {
        let mut i = 0;
        while (i + 1) < self.ops.len() {
            match &vec![&self.ops[i], &self.ops[i+1]][..] {
                [&Add(a), &Add(b)] => {
                    self.ops[i] = Add(a + b);
                    self.ops.remove(i + 1);
                },
                [&Mov(a), &Mov(b)] => {
                    self.ops[i] = Mov(a + b);
                    self.ops.remove(i + 1);
                },
                _ => i += 1
            }
        }
    }

    fn get(&self) -> &[Op] {
        &self.ops[..]
    }

    fn new() -> OpStream {
        OpStream { ops: Vec::new() }
    }
}

struct State {
    index: usize,
    memory: [u8; MEMSIZE]
}

impl State {
    fn new() -> State {
        State { index: 0, memory: [0; MEMSIZE] }
    }

    fn peek(&self) -> u8 {
        self.memory[self.index % MEMSIZE]
    }

    fn poke(&mut self, value: u8) {
        self.memory[self.index % MEMSIZE] = value;
    }

    fn step(&mut self, op: &Op) {
        match op {
            &Add(i) => { let x = self.peek(); self.poke(x + i); },
            &Mov(n) => self.index += n,
            &In => {
                self.poke(stdio::stdin().read_u8().unwrap());
            },
            &Out => {
                stdio::stdout().write_u8(self.peek()).unwrap();
            },
            &Loop(ref ops) => {
                while self.peek() != 0 {
                    self.run(ops.get());
                }
            }
        }
    }

    fn run(&mut self, ops: &[Op]) {
        for op in ops {
            self.step(op);
        }
    }
}

#[test]
fn test_state_peek() {
    let mut state = State::new();
    state.memory[state.index] = 23;
    assert_eq!(23, state.peek());
    state.index = 5;
    state.memory[state.index] = 42;
    assert_eq!(42, state.peek());
}

#[test]
fn test_state_poke() {
    let mut state = State::new();
    state.poke(23);
    assert_eq!(23, state.memory[state.index]);
    state.index = 5;
    state.poke(42);
    assert_eq!(42, state.memory[state.index]);
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        let reader = reader(&Path::new(filename));
        let mut chars = reader.chars().peekable();

        let mut opstream = OpStream::new();
        loop {
            match parse(&mut chars) {
                Something(op) => opstream.add(op),
                EOF => break,
                _ => {}
            }
        }

        opstream.optimize();

        State::new().run(opstream.get());
    }
}

fn parse<T: io::Read>(mut chars: &mut std::iter::Peekable<io::Chars<T>>) -> ParserResult {
    match chars.next() {
        Some(Ok(c)) => match c {
            '+' => Something(Add(1)),
            '-' => Something(Add(-1)),
            '<' => Something(Mov(-1)),
            '>' => Something(Mov(1)),
            ',' => Something(In),
            '.' => Something(Out),
            '[' => {
                let mut childstream = OpStream::new();
                while chars.peek() != Some(&Ok(']')) {
                    match parse(&mut chars) {
                        Something(op) => childstream.add(op),
                        Nothing => {},
                        EOF => panic!()
                    }
                }
                chars.next();
                childstream.optimize();
                Something(Loop(childstream))
            },
            _ => Nothing  // other characters
        },
        _ => EOF
    }
}

fn reader(path: &Path) -> io::BufReader<fs::File> {
    io::BufReader::new(fs::File::open(path).unwrap())
}
<|endoftext|>


<commit_before>use std::env;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::clone::Clone;
use std::str::Lines;
use std::io::prelude::*;
use std::io::BufReader;

// Device Tree stucture
/*
struct DeviceTree<'a> {
	version: u32,
	boot_cpuid: u32,
	reserved_mem: Vec<(u64, u64)>,
	root: Node<'a, 'a>,
}

struct DeviceNode<'a, 'b> {
	name: String,
	props: Vec<(String, Property<'a>)>,
	children: Vec<DeviceNode<'b, 'b>>,
}

enum Property<'a> {
	Empty,
	Cells(Vec<u32>),
	String(String),
	ByteString(Vec<u8>),
	Combo(Vec<&'a Property<'a>>),
}
*/

// File tracking
#[derive(Debug)]
struct ParsedFile<'a> {
	path: &'a Path,
	file: File,
	method: IncludeMethod<'a>,
	included_files: Vec<ParsedFile<'a>>,
}

#[derive(Debug)]
enum IncludeMethod<'a> {
	DTS,
	CPP(&'a File, Vec<FileMapping>),
}

#[derive(Debug)]
struct FileMapping {
	parent_start: usize,
	child_start: usize,
	len: usize,
}

#[derive(Debug)]
enum LinemarkerFlag {
	Start,
	Return,
	System,
	Extern,
}

// Change tracking
/*
struct Change<'a> {
	file: File,
	line: usize,
	// maybe point to node?
	name: String,
	value: Property<'a>,
}
*/

impl<'a> ParsedFile<'a> {
	fn new(path: &'a Path, method: IncludeMethod<'a>) -> ParsedFile<'a> {
		ParsedFile {
			path: path,
			file: File::open(path).unwrap(),
			method: method,
			included_files: vec![],
		}
	}
}
/*
impl<'a> fmt::Display for ParsedFile<'a> {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{:?}: {}", self.file, self.method)
		//Name: method
		//|- Next one
	}
}
*/

const CPP_OUTPUT_NAME: &'static str = "dts_viewer_tmp.dts";

fn main() {
	// let file_name = "am335x-boneblack.dts";
	let file_name = match env::args().nth(1) {
		None => {
			println!("You forgot the dts file, you dummy");
			return;
		}
		Some(x) => x,
	};

	let arch = "arm";
	let dts_folder = format!("arch/{}/boot/dts/", arch);
	let file_path = format!("{}{}", dts_folder, file_name);

	let include_output = Command::new("arm-linux-gnueabi-gcc")
		.args(&["-H", "-E", "-nostdinc"])
		.arg(format!("-I{}", dts_folder))
		.arg(format!("-I{}include/", dts_folder))
		.args(&["-undef", "-D__DTS__", "-x", "assembler-with-cpp"])
		.args(&["-o", CPP_OUTPUT_NAME])
		.arg(&file_path)
		.output()
		.expect("failed to execute process"); //TODO: properly handle errors

	let global_file = File::open(CPP_OUTPUT_NAME).unwrap();

	let cpp_output = String::from_utf8_lossy(&include_output.stderr);
	println!("{}", cpp_output);

	let mut main_file = ParsedFile::new(&Path::new(&file_path),
										IncludeMethod::CPP(&global_file, vec![]));

	parse_cpp_output(&mut cpp_output.lines(), &mut main_file, &global_file, 0);

	let global_buffer = BufReader::new(File::open(CPP_OUTPUT_NAME).unwrap());
	let mut parsed_lines = global_buffer.lines()
		.enumerate()
		.filter(|&(_, ref line)| match *line {
			Ok(ref l) => l.starts_with('#'),
			Err(_) => false,
		})
		.map(|(line_num, line)| {
			let line = line.unwrap();
			let tokens: Vec<&str> = line.split('"').map(|s| s.trim_matches('#').trim()).collect();
			let child_num: usize = tokens[0].parse().unwrap();
			let flag = match tokens[2].parse().unwrap_or(0) { //TODO: make conversion function
				1 => Some(LinemarkerFlag::Start),
				2 => Some(LinemarkerFlag::Return),
				3 => Some(LinemarkerFlag::System),
				4 => Some(LinemarkerFlag::Extern),
				_ => None,
			};
			(line_num + 1, child_num, tokens[1].to_string(), flag)
		})
		.peekable();

	while let Some((path, mapping)) =
		parse_cpp_linemarkers(&parsed_lines.next(), &parsed_lines.peek()) {
		if mapping.len > 1 {
			println!("{:?} {:?}", path, mapping);
			// find file in ParsedFile tree
			// add mapping to vec
		}
	}
}

fn count_begining_chars(s: &str, c: char) -> usize {
	let mut count: usize = 0;
	for sc in s.chars() {
		if sc == c {
			count += 1;
		} else {
			break;
		}
	}

	count
}

fn parse_cpp_output<'a>(lines: &mut Lines<'a>,
						parrent_file: &mut ParsedFile<'a>,
						global_file: &'a File,
						depth: usize) {
	while let Some(line) = lines.clone().next() { //TODO: try to use Peekable again. Had problems with recursion before
		let count = count_begining_chars(line, '.');

		if count == 0 {
			return;
		} else if count < depth {
			return;
		} else if count == depth {
			return;
		} else if count > depth && (count - depth) == 1 {
			parrent_file.included_files.push(
					ParsedFile::new(
							&Path::new(lines.next()
								.unwrap()
								.trim_left_matches('.')
								.trim_left()),
							IncludeMethod::CPP(&global_file, vec![])
			));
			parse_cpp_output(lines,
							 parrent_file.included_files.last_mut().unwrap(),
							 global_file,
							 depth + 1);
		} else {
			panic!("Match that should not have been reached.");
		}
	}
}

fn parse_cpp_linemarkers(current: &Option<(usize, usize, String, Option<LinemarkerFlag>)>,
						next: &Option<&(usize, usize, String, Option<LinemarkerFlag>)>)
						-> Option<(PathBuf, FileMapping)> {
	if let Some((c_line_num, c_child_num, ref c_path, _)) = *current {
		if let Some(&(n_line_num, _, _, _)) = *next {
			Some((PathBuf::from(c_path),
				FileMapping {
					parent_start: c_line_num + 1,
					child_start: c_child_num,
					len: n_line_num - c_line_num,
			}))
		} else {
			let last_line = BufReader::new(File::open(CPP_OUTPUT_NAME).unwrap())
				.lines()
				.count(); //TODO: don't use lines() as that allocates new Strings on the heap
			Some((PathBuf::from(c_path),
				FileMapping {
					parent_start: c_line_num + 1,
					child_start: c_child_num,
					len: last_line - c_line_num, // TODO: find length of file
			}))
		}
	} else {
		None
	}
}
<commit_msg>Use Path and PathBuf where possible<commit_after>use std::env;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::clone::Clone;
use std::str::Lines;
use std::io::prelude::*;
use std::io::BufReader;

// Device Tree stucture
/*
struct DeviceTree<'a> {
	version: u32,
	boot_cpuid: u32,
	reserved_mem: Vec<(u64, u64)>,
	root: Node<'a, 'a>,
}

struct DeviceNode<'a, 'b> {
	name: String,
	props: Vec<(String, Property<'a>)>,
	children: Vec<DeviceNode<'b, 'b>>,
}

enum Property<'a> {
	Empty,
	Cells(Vec<u32>),
	String(String),
	ByteString(Vec<u8>),
	Combo(Vec<&'a Property<'a>>),
}
*/

// File tracking
#[derive(Debug)]
struct ParsedFile<'a> {
	path: &'a Path,
	file: File,
	method: IncludeMethod<'a>,
	included_files: Vec<ParsedFile<'a>>,
}

#[derive(Debug)]
enum IncludeMethod<'a> {
	DTS,
	CPP(&'a File, Vec<FileMapping>),
}

#[derive(Debug)]
struct FileMapping {
	parent_start: usize,
	child_start: usize,
	len: usize,
}

#[derive(Debug)]
enum LinemarkerFlag {
	Start,
	Return,
	System,
	Extern,
}

// Change tracking
/*
struct Change<'a> {
	file: File,
	line: usize,
	// maybe point to node?
	name: String,
	value: Property<'a>,
}
*/

impl<'a> ParsedFile<'a> {
	fn new(path: &'a Path, method: IncludeMethod<'a>) -> ParsedFile<'a> {
		ParsedFile {
			path: path,
			file: File::open(path).unwrap(),
			method: method,
			included_files: vec![],
		}
	}
}
/*
impl<'a> fmt::Display for ParsedFile<'a> {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{:?}: {}", self.file, self.method)
		//Name: method
		//|- Next one
	}
}
*/

const CPP_OUTPUT_NAME: &'static str = "dts_viewer_tmp.dts";

fn main() {
	// let file_name = "am335x-boneblack.dts";
	let file_name = match env::args().nth(1) {
		None => {
			println!("You forgot the dts file, you dummy");
			return;
		}
		Some(x) => x,
	};

	let arch = "arm";

	let dts_folder = PathBuf::from("arch").join(arch).join("boot/dts/");
	let file_path = dts_folder.join(file_name);

	let include_output = Command::new("arm-linux-gnueabi-gcc")
		.args(&["-H", "-E", "-nostdinc"])
		.args(&["-I", dts_folder.to_str().unwrap()])
		.args(&["-I", dts_folder.join("include/").to_str().unwrap()])
		.args(&["-undef", "-D__DTS__", "-x", "assembler-with-cpp"])
		.args(&["-o", CPP_OUTPUT_NAME])
		.arg(&file_path)
		.output()
		.expect("failed to execute process"); //TODO: properly handle errors

	let global_file = File::open(CPP_OUTPUT_NAME).unwrap();

	let cpp_output = String::from_utf8_lossy(&include_output.stderr);
	println!("{}", cpp_output);

	let mut main_file = ParsedFile::new(&Path::new(&file_path),
										IncludeMethod::CPP(&global_file, vec![]));

	parse_cpp_output(&mut cpp_output.lines(), &mut main_file, &global_file, 0);

	let global_buffer = BufReader::new(File::open(CPP_OUTPUT_NAME).unwrap());
	let mut parsed_lines = global_buffer.lines()
		.enumerate()
		.filter(|&(_, ref line)| match *line {
			Ok(ref l) => l.starts_with('#'),
			Err(_) => false,
		})
		.map(|(line_num, line)| {
			let line = line.unwrap();
			let tokens: Vec<&str> = line.split('"').map(|s| s.trim_matches('#').trim()).collect();
			let child_num: usize = tokens[0].parse().unwrap();
			let flag = match tokens[2].parse().unwrap_or(0) { //TODO: make conversion function
				1 => Some(LinemarkerFlag::Start),
				2 => Some(LinemarkerFlag::Return),
				3 => Some(LinemarkerFlag::System),
				4 => Some(LinemarkerFlag::Extern),
				_ => None,
			};
			(line_num + 1, child_num, PathBuf::from(tokens[1]), flag)
		})
		.peekable();

	while let Some((path, mapping)) =
		parse_cpp_linemarkers(&parsed_lines.next(), &parsed_lines.peek()) {
		if mapping.len > 1 {
			println!("{:?} {:?}", path, mapping);
			// find file in ParsedFile tree
			// add mapping to vec
		}
	}
}

fn count_begining_chars(s: &str, c: char) -> usize {
	let mut count: usize = 0;
	for sc in s.chars() {
		if sc == c {
			count += 1;
		} else {
			break;
		}
	}

	count
}

fn parse_cpp_output<'a>(lines: &mut Lines<'a>,
						parrent_file: &mut ParsedFile<'a>,
						global_file: &'a File,
						depth: usize) {
	while let Some(line) = lines.clone().next() { //TODO: try to use Peekable again. Had problems with recursion before
		let count = count_begining_chars(line, '.');

		if count == 0 {
			return;
		} else if count < depth {
			return;
		} else if count == depth {
			return;
		} else if count > depth && (count - depth) == 1 {
			parrent_file.included_files.push(
					ParsedFile::new(
							&Path::new(lines.next()
								.unwrap()
								.trim_left_matches('.')
								.trim_left()),
							IncludeMethod::CPP(&global_file, vec![])
			));
			parse_cpp_output(lines,
							 parrent_file.included_files.last_mut().unwrap(),
							 global_file,
							 depth + 1);
		} else {
			panic!("Match that should not have been reached.");
		}
	}
}

fn parse_cpp_linemarkers<'a>(current: &'a Option<(usize, usize, PathBuf, Option<LinemarkerFlag>)>,
						next: &Option<&(usize, usize, PathBuf, Option<LinemarkerFlag>)>)
						-> Option<(&'a Path, FileMapping)> {
	if let Some((c_line_num, c_child_num, ref c_path, _)) = *current {
		if let Some(&(n_line_num, _, _, _)) = *next {
			Some((c_path,
				FileMapping {
					parent_start: c_line_num + 1,
					child_start: c_child_num,
					len: n_line_num - c_line_num,
			}))
		} else {
			let last_line = BufReader::new(File::open(CPP_OUTPUT_NAME).unwrap())
				.lines()
				.count(); //TODO: don't use lines() as that allocates new Strings on the heap
			Some((c_path,
				FileMapping {
					parent_start: c_line_num + 1,
					child_start: c_child_num,
					len: last_line - c_line_num, // TODO: find length of file
			}))
		}
	} else {
		None
	}
}
<|endoftext|>


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

#[allow(dead_code)]

use ast::Ast;
use parser::Parser;

use ast::ExprAst;
use ast::SymbolNode;

use eval::Evaler;

mod ast;
mod parser;
mod eval;
mod test;

fn help() {
    println!("rust-scm: prog");
}

#[allow(dead_code)]
fn main() {

    let b1 = box ExprAst::Symbol(SymbolNode::new("quote".to_string()));
    let b2 = box ExprAst::Symbol(SymbolNode::new("quote".to_string()));

    if b1 == b2 {
        println!("cmp");
    } else {
        println!("no cmp");
    }

    let mut evaler = Evaler::new();
    let res = evaler.eval("11".to_string());
    res.print();

    let mut parser = Parser::new();
    let res = parser.load("11".to_string());
    //assert!(res.as_int() == 11);
    res.print();

    let args = os::args();

    if args.len() < 2 {
        help();
        os::set_exit_status(1);
        return;
    }

    let program = args[0].as_slice();
    println!("args: {} program: {}", args, program);
    let code = match io::File::open(&Path::new(args[1].as_slice())) {
        Ok(mut file) => file.read_to_string().unwrap(),
        Err(_) => {
            os::set_exit_status(1);
            return
        }
    };
    let parser = parser::Parser::new();
    let res = UnicodeChar::is_numeric('a');
    println!("res: {}", res);
    println!("parser: {}", parser);
    println!("code: {}", code);
}
<commit_msg>cleanup<commit_after>use std::os;
use std::io;

#[allow(dead_code)]

use ast::Ast;
use parser::Parser;

use ast::ExprAst;
use ast::SymbolNode;

use eval::Evaler;

mod ast;
mod parser;
mod eval;
mod test;

fn help() {
    println!("rust-scm: prog");
}

#[allow(dead_code)]
fn main() {

    let mut evaler = Evaler::new();
    let res = evaler.eval("11".to_string());
    res.print();

    let mut parser = Parser::new();
    let res = parser.load("11".to_string());
    //assert!(res.as_int() == 11);
    res.print();

    let args = os::args();

    if args.len() < 2 {
        help();
        os::set_exit_status(1);
        return;
    }

    let program = args[0].as_slice();
    println!("args: {} program: {}", args, program);
    let code = match io::File::open(&Path::new(args[1].as_slice())) {
        Ok(mut file) => file.read_to_string().unwrap(),
        Err(_) => {
            os::set_exit_status(1);
            return
        }
    };
    let parser = parser::Parser::new();
    let res = UnicodeChar::is_numeric('a');
    println!("res: {}", res);
    println!("parser: {}", parser);
    println!("code: {}", code);
}
<|endoftext|>


<commit_before>#![allow(unknown_lints)]
#![allow(unused_doc_comments)]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "allocator", feature(alloc_system, global_allocator, allocator_api))]
#[cfg(feature = "allocator")]
extern crate alloc_system;
#[cfg(feature = "allocator")]
use alloc_system::System;
#[cfg(feature = "allocator")]
#[global_allocator]
static A: System = System;

extern crate amy;
extern crate base32;
extern crate base64;
extern crate bincode;
extern crate byteorder;
extern crate chrono;
#[macro_use]
extern crate error_chain;
extern crate fnv;
extern crate fs_extra;
extern crate getopts;
extern crate http_range;
extern crate httparse;
#[macro_use]
extern crate lazy_static;
extern crate memmap;
extern crate metrohash;
extern crate net2;
extern crate nix;
extern crate num_bigint;
extern crate openssl;
extern crate rand;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate shellexpand;
extern crate toml;
extern crate url;
extern crate vecio;

extern crate adns;
extern crate synapse_bencode as bencode;
extern crate synapse_rpc as rpc_lib;
extern crate synapse_session as session;

#[macro_use]
mod log;
mod args;
mod buffers;
mod handle;
mod torrent;
mod util;
mod socket;
mod disk;
mod tracker;
mod control;
mod listener;
mod rpc;
mod throttle;
mod config;
mod stat;
mod init;

// We need to do this for the log macros
use log::LogLevel;
use std::sync::atomic;
use std::process;

pub const DHT_EXT: (usize, u8) = (7, 1);
pub const EXT_PROTO: (usize, u8) = (5, 0x10);
pub const UT_META_ID: u8 = 9;
pub const UT_PEX_ID: u8 = 11;

/// Throttler max token amount
pub const THROT_TOKS: usize = 2 * 1024 * 1024;

pub static SHUTDOWN: atomic::AtomicBool = atomic::AtomicBool::new(false);

lazy_static! {
    pub static ref CONFIG: config::Config = { config::Config::load() };
    pub static ref PEER_ID: [u8; 20] = {
        use rand::{self, Rng};

        let mut pid = [0u8; 20];
        let prefix = b"-SY0002-";
        for i in 0..prefix.len() {
            pid[i] = prefix[i];
        }

        let mut rng = rand::thread_rng();
        for i in prefix.len()..20 {
            pid[i] = rng.gen::<u8>();
        }
        pid
    };
    pub static ref DL_TOKEN: String = { util::random_string(20) };
}

fn main() {
    let args = args::args();
    match init::init(args) {
        Ok(()) => {}
        Err(()) => {
            error!("Failed to initialize synapse!");
            process::exit(1);
        }
    }
    info!("Initialized, starting!");
    match init::run() {
        Ok(()) => process::exit(0),
        Err(()) => process::exit(1),
    }
}
<commit_msg>Update Peer ID to 0010<commit_after>#![allow(unknown_lints)]
#![allow(unused_doc_comments)]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "allocator", feature(alloc_system, global_allocator, allocator_api))]
#[cfg(feature = "allocator")]
extern crate alloc_system;
#[cfg(feature = "allocator")]
use alloc_system::System;
#[cfg(feature = "allocator")]
#[global_allocator]
static A: System = System;

extern crate amy;
extern crate base32;
extern crate base64;
extern crate bincode;
extern crate byteorder;
extern crate chrono;
#[macro_use]
extern crate error_chain;
extern crate fnv;
extern crate fs_extra;
extern crate getopts;
extern crate http_range;
extern crate httparse;
#[macro_use]
extern crate lazy_static;
extern crate memmap;
extern crate metrohash;
extern crate net2;
extern crate nix;
extern crate num_bigint;
extern crate openssl;
extern crate rand;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate shellexpand;
extern crate toml;
extern crate url;
extern crate vecio;

extern crate adns;
extern crate synapse_bencode as bencode;
extern crate synapse_rpc as rpc_lib;
extern crate synapse_session as session;

#[macro_use]
mod log;
mod args;
mod buffers;
mod handle;
mod torrent;
mod util;
mod socket;
mod disk;
mod tracker;
mod control;
mod listener;
mod rpc;
mod throttle;
mod config;
mod stat;
mod init;

// We need to do this for the log macros
use log::LogLevel;
use std::sync::atomic;
use std::process;

pub const DHT_EXT: (usize, u8) = (7, 1);
pub const EXT_PROTO: (usize, u8) = (5, 0x10);
pub const UT_META_ID: u8 = 9;
pub const UT_PEX_ID: u8 = 11;

/// Throttler max token amount
pub const THROT_TOKS: usize = 2 * 1024 * 1024;

pub static SHUTDOWN: atomic::AtomicBool = atomic::AtomicBool::new(false);

lazy_static! {
    pub static ref CONFIG: config::Config = { config::Config::load() };
    pub static ref PEER_ID: [u8; 20] = {
        use rand::{self, Rng};

        let mut pid = [0u8; 20];
        let prefix = b"-SY0010-";
        for i in 0..prefix.len() {
            pid[i] = prefix[i];
        }

        let mut rng = rand::thread_rng();
        for i in prefix.len()..20 {
            pid[i] = rng.gen::<u8>();
        }
        pid
    };
    pub static ref DL_TOKEN: String = { util::random_string(20) };
}

fn main() {
    let args = args::args();
    match init::init(args) {
        Ok(()) => {}
        Err(()) => {
            error!("Failed to initialize synapse!");
            process::exit(1);
        }
    }
    info!("Initialized, starting!");
    match init::run() {
        Ok(()) => process::exit(0),
        Err(()) => process::exit(1),
    }
}
<|endoftext|>


<commit_before>use std::net::{TcpListener, TcpStream, Shutdown};
use std::io::prelude::*;
use std::io;

fn main() {

    let listener = TcpListener::bind("127.0.0.1:8000").expect("failed to start server");

    fn handle_client(stream: TcpStream) {
        println!("Hello, world!");

        let mut ostream = stream.try_clone().expect("couldn't clone");
        let mut reader = io::BufReader::new(stream);
        let mut request = String::new();

        let a = reader.read_line(&mut request).expect("read failed");
        println!("{:?} - {:?}", a, request);

        ostream.write_all(b"HTTP/1.0 200 OK\nContent-Type: text/html\n\nHello there!").expect("write failed");

        ostream.flush().expect("stream flushed");
        match ostream.shutdown(Shutdown::Both) {
            Ok(_) => println!("shutdown call successful"),
            Err(e) => println!("shutdown call failed, with error: {:?}", e)
        };
    }

    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                handle_client(stream);
            }
            Err(e) => println!("{:?}", e)
        }
    }
}
<commit_msg>1. Remove stream shutdown 2. Stream reading in its own method 3. Read header line by line. Stop at empty line.<commit_after>use std::net::{TcpListener, TcpStream};
use std::io::prelude::*;
use std::io;

fn main() {

    let listener = TcpListener::bind("127.0.0.1:8000").expect("failed to start server");

    fn read_request(stream: &TcpStream) -> String {
        let mut istream = stream.try_clone().expect("couldn't clone");
        let mut reader = io::BufReader::new(stream);
        let mut request = String::new();
        let mut l;
        for line in reader.lines() {
            l = line.unwrap();
            if l == "" {
                istream.flush();
                break;
            } else {
                request.push_str(&l);
                request.push_str("\n");
            }
        }
        println!("finished reading");
        request
    }

    fn handle_client(stream: TcpStream) {
        println!("Hello, world!");

        let mut ostream = stream.try_clone().expect("couldn't clone");
        let mut request = String::new();

        request = read_request(&stream);
        println!("{:?} - {:?}", request.len(), request);

        ostream.write_all(b"HTTP/1.0 200 OK\nContent-Type: text/html\n\nHello there!").expect("write failed");

        ostream.flush().expect("stream flushed");
    }

    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                handle_client(stream);
            }
            Err(e) => println!("{:?}", e)
        }
    }
}
<|endoftext|>


<commit_before>use macroquad::prelude::*;

use colour::Colour;
use graph::{Graph, Position};
use grid::Grid;

mod colour;
mod graph;
mod grid;

fn macroquad_colour(colour: Colour) -> Color {
    match colour {
        Colour::Red => color_u8!(255, 0, 0, 255),
        Colour::Yellow => color_u8!(255, 255, 0, 255),
        Colour::Green => color_u8!(0, 176, 0, 255),
        Colour::LightBrown => color_u8!(255, 204, 102, 255),
        Colour::Purple => color_u8!(128, 0, 128, 255),
        Colour::Cyan => color_u8!(0, 255, 255, 255),
        Colour::Blue => color_u8!(0, 0, 255, 255),
        Colour::Fuchsia => color_u8!(255, 0, 255, 255),
    }
}

fn draw_cell(grid_x: f32, grid_y: f32, cell_size: f32, position: &Position, colour: Colour) {
    let color = macroquad_colour(colour);
    draw_rectangle(
        grid_x + cell_size * position.column as f32,
        grid_y + cell_size * position.row as f32,
        cell_size,
        cell_size,
        color,
    );
}

struct Ui {
    /// Size of the grid in cells.
    size: usize,

    /// Size of the grid in pixels.  Assumes the grid is always square.
    grid_size: f32,

    /// Offset of the grid relative to the whole window along the horizontal axis.
    grid_x: f32,

    /// Offset of the grid relative to the whole window along the vertical axis.
    grid_y: f32,
}

impl Ui {
    fn create(size: usize) -> Ui {
        let mut ui = Ui {
            size,
            grid_size: 0.0,
            grid_x: 0.0,
            grid_y: 0.0,
        };

        ui.resize();

        ui
    }

    fn resize(&mut self) {
        let screen_height = screen_height();
        let screen_width = screen_width();

        let grid_size = screen_height.min(screen_width);
        self.grid_size = grid_size;
        self.grid_x = (screen_width - grid_size) / 2.0;
        self.grid_y = (screen_height - grid_size) / 2.0;
    }

    fn render(&self, graph: &Graph) {
        clear_background(BLACK);

        let grid_x = self.grid_x;
        let grid_y = self.grid_y;
        let cell_size = self.cell_size();

        for component in graph.neighbours.keys() {
            for position in &graph.components[component].cells {
                draw_cell(grid_x, grid_y, cell_size, position, graph.components[component].colour);
            }
        }
    }

    fn cell_size(&self) -> f32 {
        self.grid_size / self.size as f32
    }

    fn cell_position(&self, raw_position: (f32, f32)) -> Option<Position> {
        let (raw_x, raw_y) = raw_position;

        let cell_size = self.cell_size();
        let x = (raw_x - self.grid_x) / cell_size;
        let y = (raw_y - self.grid_y) / cell_size;

        let size = self.size as f32;
        if x < 0.0 || y < 0.0 || x > size || y > size {
            // Out of bounds, nothing to do
            None
        } else {
            Some(Position{column: x.floor() as usize, row: y.floor() as usize})
        }
    }

    fn handle_click(&self, graph: &mut Graph) {
        if !is_mouse_button_pressed(MouseButton::Left) {
            return;
        }

        if let Some(position) = self.cell_position(mouse_position()) {
            let clicked_component = graph.find_component(&position);
            let colour = clicked_component.colour;

            println!("Detected click at cell ({}, {}) with colour {:#?}", position.column, position.row, colour);

            graph.change_colour_of_component_at(&Position{column: 0_usize, row: 0_usize}, colour);
        }
    }
}

enum GameState {
    Solving,
    Solved,
}

#[macroquad::main("Flood-It")]
async fn main() {
    let size = 8;
    let grid = Grid::generate(size);
    let mut graph = Graph::create(&grid);
    println!("{:#?}", graph);

    let mut ui = Ui::create(size);

    let mut state = GameState::Solving;

    loop {
        if let Some(KeyCode::Q) = get_last_key_pressed() {
            break;
        }

        ui.handle_click(&mut graph);

        ui.resize();
        ui.render(&graph);

        match state {
            GameState::Solving =>
            if graph.components.len() == 1 {
                state = GameState::Solved;
                println!("Done");
            }
            GameState::Solved => (),
        }

        next_frame().await
    }
}
<commit_msg>Move game state into a field in the new struct Game<commit_after>use macroquad::prelude::*;

use colour::Colour;
use graph::{Graph, Position};
use grid::Grid;

mod colour;
mod graph;
mod grid;

fn macroquad_colour(colour: Colour) -> Color {
    match colour {
        Colour::Red => color_u8!(255, 0, 0, 255),
        Colour::Yellow => color_u8!(255, 255, 0, 255),
        Colour::Green => color_u8!(0, 176, 0, 255),
        Colour::LightBrown => color_u8!(255, 204, 102, 255),
        Colour::Purple => color_u8!(128, 0, 128, 255),
        Colour::Cyan => color_u8!(0, 255, 255, 255),
        Colour::Blue => color_u8!(0, 0, 255, 255),
        Colour::Fuchsia => color_u8!(255, 0, 255, 255),
    }
}

fn draw_cell(grid_x: f32, grid_y: f32, cell_size: f32, position: &Position, colour: Colour) {
    let color = macroquad_colour(colour);
    draw_rectangle(
        grid_x + cell_size * position.column as f32,
        grid_y + cell_size * position.row as f32,
        cell_size,
        cell_size,
        color,
    );
}

struct Ui {
    /// Size of the grid in cells.
    size: usize,

    /// Size of the grid in pixels.  Assumes the grid is always square.
    grid_size: f32,

    /// Offset of the grid relative to the whole window along the horizontal axis.
    grid_x: f32,

    /// Offset of the grid relative to the whole window along the vertical axis.
    grid_y: f32,
}

impl Ui {
    fn create(size: usize) -> Ui {
        let mut ui = Ui {
            size,
            grid_size: 0.0,
            grid_x: 0.0,
            grid_y: 0.0,
        };

        ui.resize();

        ui
    }

    fn resize(&mut self) {
        let screen_height = screen_height();
        let screen_width = screen_width();

        let grid_size = screen_height.min(screen_width);
        self.grid_size = grid_size;
        self.grid_x = (screen_width - grid_size) / 2.0;
        self.grid_y = (screen_height - grid_size) / 2.0;
    }

    fn render(&self, graph: &Graph) {
        clear_background(BLACK);

        let grid_x = self.grid_x;
        let grid_y = self.grid_y;
        let cell_size = self.cell_size();

        for component in graph.neighbours.keys() {
            for position in &graph.components[component].cells {
                draw_cell(grid_x, grid_y, cell_size, position, graph.components[component].colour);
            }
        }
    }

    fn cell_size(&self) -> f32 {
        self.grid_size / self.size as f32
    }

    fn cell_position(&self, raw_position: (f32, f32)) -> Option<Position> {
        let (raw_x, raw_y) = raw_position;

        let cell_size = self.cell_size();
        let x = (raw_x - self.grid_x) / cell_size;
        let y = (raw_y - self.grid_y) / cell_size;

        let size = self.size as f32;
        if x < 0.0 || y < 0.0 || x > size || y > size {
            // Out of bounds, nothing to do
            None
        } else {
            Some(Position{column: x.floor() as usize, row: y.floor() as usize})
        }
    }

    fn handle_click(&self, graph: &mut Graph) {
        if !is_mouse_button_pressed(MouseButton::Left) {
            return;
        }

        if let Some(position) = self.cell_position(mouse_position()) {
            let clicked_component = graph.find_component(&position);
            let colour = clicked_component.colour;

            println!("Detected click at cell ({}, {}) with colour {:#?}", position.column, position.row, colour);

            graph.change_colour_of_component_at(&Position{column: 0_usize, row: 0_usize}, colour);
        }
    }
}

enum GameState {
    Solving,
    Solved,
}

struct Game {
    state: GameState
}

impl Game {
    fn create() -> Self {
        Self {
            state: GameState::Solving,
        }
    }
}

#[macroquad::main("Flood-It")]
async fn main() {
    let size = 8;
    let grid = Grid::generate(size);
    let mut graph = Graph::create(&grid);
    println!("{:#?}", graph);

    let mut ui = Ui::create(size);

    let mut game = Game::create();

    loop {
        if let Some(KeyCode::Q) = get_last_key_pressed() {
            break;
        }

        ui.handle_click(&mut graph);

        ui.resize();
        ui.render(&graph);

        match game.state {
            GameState::Solving =>
            if graph.components.len() == 1 {
                game.state = GameState::Solved;
                println!("Done");
            }
            GameState::Solved => (),
        }

        next_frame().await
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate walkdir;
extern crate twox_hash;

use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::path::Path;

use clap::{App, Arg};
use walkdir::WalkDir;
use twox_hash::XxHash;
use std::hash::Hasher;

struct Stats {
    file_count: u64,
    total_size: u64,
    duplicate_count: u64,
}

fn main() {
    let matches = App::new("dupr")
        .version("0.1.0")
        .author("Mike Sampson")
        .about("Duplicate file finder")
        .arg(
            Arg::with_name("DIR")
                .help("Directory to process")
                .required(true),
        )
        .arg(
            Arg::with_name("summary")
                .short("s")
                .long("summary")
                .help("Print out summary information after duplicates")
        )
        .get_matches();

    let mut files = HashMap::new();

    let mut stats = Stats {
        file_count: 0,
        total_size: 0,
        duplicate_count: 0,
    };

    for entry in WalkDir::new(matches.value_of("DIR").unwrap()) {
        let entry = entry.unwrap();

        if !entry.file_type().is_file() {
            continue;
        }

        let metadata = entry.metadata().unwrap();

        if metadata.len() == 0 {
            continue;
        }

        stats.file_count += 1;
        stats.total_size += metadata.len();

        let path = entry.path().to_path_buf();

        files.entry(metadata.len()).or_insert(Vec::new()).push(path);
    }

    for f_paths in files.values() {
        if f_paths.len() == 1 {
            continue;
        }

        let mut hashes = HashMap::new();
        for f_path in f_paths {
            hashes
                .entry(hash_file(&f_path))
                .or_insert(Vec::new())
                .push(f_path);
        }

        for (hash, paths) in hashes {
            if paths.len() < 2 {
                continue;
            }
            stats.duplicate_count += paths.len() as u64;
            for p in paths {
                println!("{:016x} - {}", hash, p.display());
            }
        }
    }

    if matches.is_present("summary")  {
        println!(
            "Processed {} files with a total size of {} bytes. {} duplicates found.",
            stats.file_count,
            stats.total_size,
            stats.duplicate_count
        );
    }
}

fn hash_file<P: AsRef<Path>>(path: P) -> u64 {
    let mut file = File::open(path).unwrap();

    let mut hash = XxHash::with_seed(0);

    let mut buffer = [0; 32 * 1024];

    while let Ok(n) = file.read(&mut buffer) {
        if n == 0 {
            break;
        }
        hash.write(&buffer[0..n]);
    }

    hash.finish()
}
<commit_msg>Start factoring out.<commit_after>extern crate clap;
extern crate walkdir;
extern crate twox_hash;

use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

use clap::{App, Arg};
use walkdir::WalkDir;
use twox_hash::XxHash;
use std::hash::Hasher;

struct Stats {
    file_count: u64,
    total_size: u64,
    duplicate_count: u64,
}

fn collect_files(path: &str, stats: &mut Stats) -> HashMap<u64, Vec<PathBuf>> {

    let mut files = HashMap::new();

    for entry in WalkDir::new(path) {
        let entry = entry.unwrap();

        if !entry.file_type().is_file() {
            continue;
        }

        let metadata = entry.metadata().unwrap();

        if metadata.len() == 0 {
            continue;
        }

        stats.file_count += 1;
        stats.total_size += metadata.len();

        let path = entry.path().to_path_buf();

        files.entry(metadata.len()).or_insert(Vec::new()).push(path);
    }

    files
}

fn main() {
    let matches = App::new("dupr")
        .version("0.1.0")
        .author("Mike Sampson")
        .about("Duplicate file finder")
        .arg(
            Arg::with_name("DIR")
                .help("Directory to process")
                .required(true),
        )
        .arg(
            Arg::with_name("summary")
                .short("s")
                .long("summary")
                .help("Print out summary information after duplicates")
        )
        .get_matches();

    let mut stats = Stats {
        file_count: 0,
        total_size: 0,
        duplicate_count: 0,
    };

    let files = collect_files(matches.value_of("DIR").unwrap(), &mut stats);

    for f_paths in files.values() {
        if f_paths.len() == 1 {
            continue;
        }

        let mut hashes = HashMap::new();
        for f_path in f_paths {
            hashes
                .entry(hash_file(&f_path))
                .or_insert(Vec::new())
                .push(f_path);
        }

        for (hash, paths) in hashes {
            if paths.len() < 2 {
                continue;
            }
            stats.duplicate_count += paths.len() as u64;
            for p in paths {
                println!("{:016x} - {}", hash, p.display());
            }
        }
    }

    if matches.is_present("summary")  {
        println!(
            "Processed {} files with a total size of {} bytes. {} duplicates found.",
            stats.file_count,
            stats.total_size,
            stats.duplicate_count
        );
    }
}

fn hash_file<P: AsRef<Path>>(path: P) -> u64 {
    let mut file = File::open(path).unwrap();

    let mut hash = XxHash::with_seed(0);

    let mut buffer = [0; 32 * 1024];

    while let Ok(n) = file.read(&mut buffer) {
        if n == 0 {
            break;
        }
        hash.write(&buffer[0..n]);
    }

    hash.finish()
}
<|endoftext|>