<commit_before>// TODO: Fix unwraps

extern crate git2;
extern crate term_painter;

use std::error::Error;
use std::io;
use std::env;
use std::path::{Path, PathBuf};

use term_painter::{ToStyle, Color};

fn main() {
    let working_dir = match env::current_dir() {
        Ok(path) => path,
        Err(err) => {
            println!("Error getting working directory: {}", err.description());
            return;
        }
    };

    println!("{:?}", walk_dirs(&working_dir));
}

fn walk_dirs(path: &Path) -> io::Result<()> {
    let mut pending: Vec<PathBuf> = Vec::new();

    loop {
        let current_dir = if pending.len() == 0 {
            path.to_path_buf()
        } else {
            pending.pop().unwrap()
        };

        let read_result = current_dir.read_dir();

        if read_result.is_ok() {
            let iter = read_result.unwrap()
                .filter(|x| x.is_ok())
                .map(|x| x.unwrap())
                .filter(|x| match x.file_type() {
                    Ok(t) => t.is_dir(),
                    Err(_) => false,
                })
                .filter(|x| match x.path().file_name() {
                    Some(name) => {
                        let name_str = name.to_str().unwrap();

                        !name_str.starts_with(".") && !name_str.starts_with("$")
                    }
                    None => false,
                });

            for entry in iter {
                if git_changes(&entry.path()).is_err() {
                    pending.push(entry.path().to_path_buf());
                }
            }
        }

        if pending.len() == 0 {
            break;
        }
    }

    Ok(())
}

enum GitError {
    OpenRepo,
}

impl From<git2::Error> for GitError {
    fn from(_: git2::Error) -> Self {
        GitError::OpenRepo
    }
}

fn git_changes(path: &Path) -> Result<(), GitError> {
    let repo = git2::Repository::open(path)?;

    if repo.is_bare() {
        return Ok(())
    }

    let mut opts = git2::StatusOptions::new();

    opts.include_ignored(false)
        .include_untracked(true)
        .recurse_untracked_dirs(true)
        .include_unreadable_as_untracked(true)
        .disable_pathspec_match(true)
        .exclude_submodules(true);

    let statuses = repo.statuses(Some(&mut opts)).unwrap();
    let mut statuses_iter = statuses.iter()
        .filter(|x| {
            if x.status() != git2::STATUS_WT_DELETED {
                return true;
            }

            // For some reason, some files with the deleted
            // status actually still exist, so ignore these.
            let mut del_path = path.to_path_buf();
            del_path.push(x.path().unwrap());

            !del_path.exists()
        })
        .peekable();

    if statuses_iter.peek().is_none() {
        return Ok(());
    }

    println!("{}", path.to_str().unwrap());

    for entry in statuses_iter {
        let pre = match entry.status() {
            git2::STATUS_WT_DELETED => Color::BrightRed.paint("    Deleted"),
            git2::STATUS_WT_MODIFIED => Color::BrightCyan.paint("   Modified"),
            git2::STATUS_WT_NEW => Color::BrightGreen.paint("        New"),
            git2::STATUS_WT_RENAMED => Color::BrightCyan.paint("    Renamed"),
            git2::STATUS_WT_TYPECHANGE => Color::BrightCyan.paint("Typechanged"),
            _ => Color::BrightMagenta.paint("    Unknown"),
        };

        println!("  {} {}", pre, entry.path().unwrap());
    }

    Ok(())
}
<commit_msg>Moved more logic into iterator.<commit_after>// TODO: Fix unwraps

extern crate git2;
extern crate term_painter;

use std::error::Error;
use std::io;
use std::env;
use std::path::{Path, PathBuf};

use term_painter::{ToStyle, Color};

fn main() {
    let working_dir = match env::current_dir() {
        Ok(path) => path,
        Err(err) => {
            println!("Error getting working directory: {}", err.description());
            return;
        }
    };

    println!("{:?}", walk_dirs(&working_dir));
}

fn walk_dirs(path: &Path) -> io::Result<()> {
    let mut pending: Vec<PathBuf> = Vec::new();

    loop {
        let current_dir = if pending.len() == 0 {
            path.to_path_buf()
        } else {
            pending.pop().unwrap()
        };

        let read_result = current_dir.read_dir();

        if read_result.is_ok() {
            let non_repo_iter = read_result
                .unwrap()
                .filter(|x| x.is_ok())
                .map(|x| x.unwrap())
                .filter(|x| match x.file_type() {
                    Ok(t) => t.is_dir(),
                    Err(_) => false,
                })
                .filter(|x| match x.path().file_name() {
                    Some(name) => {
                        let name_str = name.to_str().unwrap();

                        !name_str.starts_with(".") && !name_str.starts_with("$")
                    }
                    None => false,
                })
                .filter(|x| git_changes(&x.path()).is_err()) // Only return folders that arent repos
                .map(|x| x.path().to_path_buf());

            for path in non_repo_iter {
                pending.push(path);
            }
        }

        if pending.len() == 0 {
            break;
        }
    }

    Ok(())
}

enum GitError {
    OpenRepo,
}

impl From<git2::Error> for GitError {
    fn from(_: git2::Error) -> Self {
        GitError::OpenRepo
    }
}

// This can become its own iterator
fn git_changes(path: &Path) -> Result<(), GitError> {
    let repo = git2::Repository::open(path)?;

    if repo.is_bare() {
        return Ok(());
    }

    let mut opts = git2::StatusOptions::new();

    opts.include_ignored(false)
        .include_untracked(true)
        .recurse_untracked_dirs(true)
        .include_unreadable_as_untracked(true)
        .disable_pathspec_match(true)
        .exclude_submodules(true);

    let statuses = repo.statuses(Some(&mut opts)).unwrap();
    let mut statuses_iter = statuses.iter()
        .filter(|x| {
            if x.status() != git2::STATUS_WT_DELETED {
                return true;
            }

            // For some reason, some files with the deleted
            // status actually still exist, so ignore these.
            let mut del_path = path.to_path_buf();
            del_path.push(x.path().unwrap());

            !del_path.exists()
        })
        .peekable();

    if statuses_iter.peek().is_none() {
        return Ok(());
    }

    println!("{}", path.to_str().unwrap());

    for entry in statuses_iter {
        let pre = match entry.status() {
            git2::STATUS_WT_DELETED => Color::BrightRed.paint("    Deleted"),
            git2::STATUS_WT_MODIFIED => Color::BrightCyan.paint("   Modified"),
            git2::STATUS_WT_NEW => Color::BrightGreen.paint("        New"),
            git2::STATUS_WT_RENAMED => Color::BrightCyan.paint("    Renamed"),
            git2::STATUS_WT_TYPECHANGE => Color::BrightCyan.paint("Typechanged"),
            _ => Color::BrightMagenta.paint("    Unknown"),
        };

        println!("  {} {}", pre, entry.path().unwrap());
    }

    Ok(())
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate regex;

use std::path::Path;

use rustc_serialize::base64::{FromBase64, ToBase64, MIME};
use rustc_serialize::hex::{ToHex};
use std::fs::File;
use std::io::Read;
use std::io::Write;
use regex::Regex;
use std::str;

fn main() {

    // ------------------------------------------------------
	let mut file = File::open("res/test.jpg").unwrap();
    let mut v = Vec::new();
    let _ = file.read_to_end(&mut v);

    let b64 = v.to_base64(MIME);
    let hex = v.to_hex();
    let fmt_base64 = format!("data:image/{};base64,{}", get_type(&hex), b64);
    let offset = fmt_base64.find(',').unwrap_or(fmt_base64.len())+1;
    let mut header = fmt_base64;
    let value: String = header.drain(..offset).collect();
    // let ggg = fmt_base64.drain(..header).collect();

     println!("{}", header);
     println!("{}", value);

    // let a = fmt_base64.find("data:image/");
    // println!("{}", None < a);

    // let a = fmt_base64.find("data:image/");
    // println!("{}", None < a);

	// let img = b64.from_base64().unwrap();
    // let mut file = File::create(&Path::new("test.jpg")).unwrap();
    // file.write_all(img.as_slice());
}

fn get_type(file: &str) -> &str {
    if Regex::new(r"^ffd8ffe0").unwrap().is_match(file) { "jpg" }
    else if Regex::new(r"^89504e47").unwrap().is_match(file){ "png" }
    else if Regex::new(r"^47494638").unwrap().is_match(file){ "gif" }
    else { panic!("invalid file") }
}<commit_msg>modularize function converting to base64<commit_after>extern crate rustc_serialize;
extern crate regex;

// use std::path::Path;

// use std::io::Write;
use std::str;
// use std::vec::Drain;

mod image_base64 {
    use std::fs::File;
    use rustc_serialize::base64::{ToBase64, MIME};
    use rustc_serialize::hex::{ToHex};
    use regex::Regex;
    use std::io::Read;
    use std::string::String;

    pub fn to_base64(path: &str) -> String {
        let mut file = File::open(path).unwrap();
        let mut v = Vec::new();
        let _ = file.read_to_end(&mut v);
        let b64 = v.to_base64(MIME);
        let hex = v.to_hex();
        return format!("data:image/{};base64,{}", get_type(&hex), b64);
    }

    fn get_type(hex: &str) -> &str {
        if Regex::new(r"^ffd8ffe0").unwrap().is_match(hex) { "jpg" }
        else if Regex::new(r"^89504e47").unwrap().is_match(hex){ "png" }
        else if Regex::new(r"^47494638").unwrap().is_match(hex){ "gif" }
        else { panic!("invalid file") }
    }
}

fn main() {

    // ------------------------------------------------------

    let fmt_base64 = image_base64::to_base64("res/test.jpg");
    let offset = fmt_base64.find(',').unwrap_or(fmt_base64.len())+1;
    let mut header = fmt_base64;
    let value: String = header.drain(..offset).collect();
    // let ggg = fmt_base64.drain(..header).collect();

     println!("{}", header);
     println!("{}", value);

    // let a = fmt_base64.find("data:image/");
    // println!("{}", None < a);

    // let a = fmt_base64.find("data:image/");
    // println!("{}", None < a);

	// let img = b64.from_base64().unwrap();
    // let mut file = File::create(&Path::new("test.jpg")).unwrap();
    // file.write_all(img.as_slice());
}<|endoftext|>


<commit_before>/*
 * PCG Random Number Generation for Rust
 *
 * Copyright 2015 John Brooks <robojeb@robojeb.xyz>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

extern crate pcg_rand;
extern crate rand;

use rand::{RngCore, Rng, FromEntropy};
use pcg_rand::{Pcg32Basic}; //Pcg32, Pcg64, Pcg32Unique, Pcg32L};

#[cfg(not(test))]
fn main() {
    let mut rng = Pcg32Basic::from_entropy();

    // print a bunch of random numbers
    println!("Here is the generator seeded from system entropy: ");
    for _ in 0..10 {
        println!("{: ^25}|{: ^25}|{: ^25}", rng.gen::<u32>(), rng.gen::<u32>(), rng.gen::<u32>());
    }

    let mut rng = Pcg32Basic::from_entropy();

    let mut x = vec![0; 1024*1024];
    rng.fill_bytes(x.as_mut_slice());

    // let mut rng : Pcg32 = OsRng::new().unwrap().gen();
    // println!("\nHere is the 32bit generator with random seed and increment: ");
    // for _ in 0..10 {
    //     println!("{: ^25}|{: ^25}|{: ^25}", rng.gen::<u32>(), rng.gen::<u32>(), rng.gen::<u32>());
    // }

    // let mut rng : Pcg64 = OsRng::new().unwrap().gen();
    // println!("\nHere is the 64bit generator with random seed and increment: ");
    // for _ in 0..10 {
    //     println!("{: ^25}|{: ^25}|{: ^25}", rng.gen::<u64>(), rng.gen::<u64>(), rng.gen::<u64>());
    // }

    // let mut rng : Pcg32L = OsRng::new().unwrap().gen();
    // println!("\nHere is the 32bit generator with 128 bits of internal state random seed and increment: ");
    // for _ in 0..10 {
    //     println!("{: ^25}|{: ^25}|{: ^25}", rng.gen::<u32>(), rng.gen::<u32>(), rng.gen::<u32>());
    // }

    // // //Later we will do party tricks
    // // //TODO: Implement the really big generators to get the party started

    // println!("\nHere we show off what two unique stream generators with the same seed can do");
    // println!("Example Code:
    // let mut urng1 = Pcg32Unique::new_unseeded();
    // let mut urng2 = Pcg32Unique::new_unseeded();
    // ");
    // let mut urng1 = Pcg32Unique::new_unseeded();
    // let mut urng2 = Pcg32Unique::new_unseeded();
    // println!("{: ^25}|{: ^25}", "Generator 1", "Generator2");
    // for _ in 0..25 {
    //     println!("{: ^25}|{: ^25}", urng1.gen::<u32>(), urng2.gen::<u32>());
    // }
    // println!("The RNGs use their location as a sequence so they diverge quickly");
}
<commit_msg>Updated main to have all the examples back<commit_after>/*
 * PCG Random Number Generation for Rust
 *
 * Copyright 2015 John Brooks <robojeb@robojeb.xyz>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

extern crate pcg_rand;
extern crate rand;

use rand::{RngCore, Rng, FromEntropy};
use pcg_rand::{Pcg32Basic, Pcg32, Pcg64, Pcg32Unique, Pcg32L};

#[cfg(not(test))]
fn main() {
    let mut rng = Pcg32Basic::new_unseeded();

    // print a bunch of random numbers
    println!("Here is the generator recovering from a (0,0) initialization: ");
    for _ in 0..10 {
        println!("{: ^25}|{: ^25}|{: ^25}", rng.gen::<u32>(), rng.gen::<u32>(), rng.gen::<u32>());
    }

    let mut rng : Pcg32 = Pcg32::from_entropy();
    println!("\nHere is the 32bit generator with random seed and increment: ");
    for _ in 0..10 {
        println!("{: ^25}|{: ^25}|{: ^25}", rng.gen::<u32>(), rng.gen::<u32>(), rng.gen::<u32>());
    }

    let mut rng : Pcg64 = Pcg64::from_entropy();
    println!("\nHere is the 64bit generator with random seed and increment: ");
    for _ in 0..10 {
        println!("{: ^25}|{: ^25}|{: ^25}", rng.gen::<u64>(), rng.gen::<u64>(), rng.gen::<u64>());
    }

    let mut rng : Pcg32L = Pcg32L::from_entropy();
    println!("\nHere is the 32bit generator with 128 bits of internal state random seed and increment: ");
    for _ in 0..10 {
        println!("{: ^25}|{: ^25}|{: ^25}", rng.gen::<u32>(), rng.gen::<u32>(), rng.gen::<u32>());
    }

    // //Later we will do party tricks
    // //TODO: Implement the really big generators to get the party started

    println!("\nHere we show off what two unique stream generators with the same seed can do");
    println!("Example Code:
    let mut urng1 = Pcg32Unique::new_unseeded();
    let mut urng2 = Pcg32Unique::new_unseeded();
    ");
    let mut urng1 = Pcg32Unique::new_unseeded();
    let mut urng2 = Pcg32Unique::new_unseeded();
    println!("{: ^25}|{: ^25}", "Generator 1", "Generator2");
    for _ in 0..25 {
        println!("{: ^25}|{: ^25}", urng1.gen::<u32>(), urng2.gen::<u32>());
    }
    println!("The RNGs use their location as a sequence so they diverge quickly");
}
<|endoftext|>


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

extern crate num;
extern crate regex;

use std::env;
use std::fmt;
use num::integer::{div_rem, Integer};
use regex::Regex;

struct Duration<T> {
    weeks: T,
    days: T,
    hours: T,
    minutes: T,
    seconds: T,
}

impl<T:Integer> Duration<T> {
    fn new() -> Duration<T> {
        Duration{ weeks: T::zero(), days: T::zero(), hours: T::zero(), minutes: T::zero(), seconds: T::zero() }
    }

    fn set_weeks(mut self, weeks: T) -> Duration<T> {
        self.weeks = weeks;
        self
    }
    fn set_days(mut self, days: T) -> Duration<T> {
        self.days = days;
        self
    }
    fn set_hours(mut self, hours: T) -> Duration<T> {
        self.hours = hours;
        self
    }
    fn set_minutes(mut self, minutes: T) -> Duration<T> {
        self.minutes = minutes;
        self
    }
    fn set_seconds(mut self, seconds: T) -> Duration<T> {
        self.seconds = seconds;
        self
    }

}

impl fmt::Display for Duration<u64> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut writing = false;
        if self.weeks != 0 {
            try!(write!(f, "{}wk", self.weeks));
            writing = true;
        }
        if self.days != 0 || writing {
            if writing { try!(write!(f, " ")); }
            try!(write!(f, "{}dy", self.days));
            writing = true;
        }
        if self.hours != 0 || writing {
            if writing { try!(write!(f, " ")); }
            try!(write!(f, "{}hr", self.hours));
            writing = true;
        }
        if self.minutes != 0 || writing {
            if writing { try!(write!(f, " ")); }
            try!(write!(f, "{}m", self.minutes));
            writing = true;
        }
        if self.seconds != 0 || writing {
            if writing { try!(write!(f, " ")); }
            try!(write!(f, "{}s", self.seconds));
            //writing = true;
        }
        Ok(())
    }
}

fn sec2duration(seconds: u64) -> Duration<u64> {
    let (minutes, seconds) = div_rem(seconds, 60);
    let (hours, minutes) = div_rem(minutes, 60);
    let (days, hours) = div_rem(hours, 24);
    let (weeks, days) = div_rem(days, 7);

    Duration::new().set_seconds(seconds).set_minutes(minutes).set_hours(hours).set_days(days).set_weeks(weeks)
}

// Converts a textual input to the number of seconds this represents. String error if something went wrong.
fn input2sec(input:String) -> Result<u64, String> {
    // TODO replace with regex! macro so the is guaranteed to be OK

    if let Some(cap) = Regex::new(r"^\s*(?P<sec>[0-9]+)(\.[0-9]+)?\s*(s|sec|seconds?)?\s*$").unwrap().captures(&input) {
        // Just numbers, interpret as seconds. Truncate the sub-seconds
        let sec: u64 = try!(try!(cap.name("sec").ok_or("0")).parse().or(Err("Invalid seconds")));
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<min>[0-9]+)\s*(m|min|minutes?)\s*((?P<sec>[0-9]+)(\.[0-9]+)?\s*(s|sec|seconds?)?)?\s*$").unwrap().captures(&input) {
        // XmYs. Truncate the subseconds
        let sec: u64 = try!(cap.name("sec").unwrap_or(&"0").parse::<u64>().or(Err("Invalid seconds")));
        let min: u64 = try!(cap.name("min").unwrap_or(&"0").parse::<u64>().or(Err("Invalid minutes")));
        Ok(min*60 + sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<min>[0-9]+):(?P<sec>[0-9][0-9])\s*$").unwrap().captures(&input) {
        // 0:00
        let sec: u64 = try!(cap.name("sec").unwrap_or(&"0").parse::<u64>().or(Err("Invalid seconds")));
        let min: u64 = try!(cap.name("min").unwrap_or(&"0").parse::<u64>().or(Err("Invalid minutes")));
        Ok(min*60 + sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)(\.[0-9]+)?\s*(ms|msec|milliseconds?)\s*$").unwrap().captures(&input) {
        // Milliseconds
        // Ignore trailing sub-milliseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid milliseconds")));
        let sec = ms / 1_000;
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)\s*(μs|μsec|microsec|microseconds?)\s*$").unwrap().captures(&input) {
        // Microseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid microseconds")));
        let sec = ms / 1_000_000;
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)\s*(ns|nsec|nanosec|nanoseconds?)\s*$").unwrap().captures(&input) {
        // Nanoseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid microseconds")));
        let sec = ms / 1_000_000_000;
        Ok(sec)
    } else {
        Err("Invalid input".to_string())
    }

}

fn prettytime(input: Vec<String>) -> Result<String, String> {
    if input.len() < 1 { return Err("No input".to_string()); }

    let input = input.join(" ");
    let seconds: u64 = try!(input2sec(input));

    let duration = sec2duration(seconds);

    Ok(format!("{}", duration))
}

fn main() {
    let args: Vec<_> = env::args().skip(1).collect();
    match prettytime(args) {
        Ok(s) => { println!("{}", s); },
        Err(s) => { println!("{}", s); std::process::exit(1); }
    }
}

#[test]
fn test_print_duration() {
    assert_eq!("", format!("{}", Duration::new()));
    assert_eq!("1s", format!("{}", Duration::new().set_seconds(1)));
    assert_eq!("1m 0s", format!("{}", Duration::new().set_minutes(1)));
    assert_eq!("1m 3s", format!("{}", Duration::new().set_minutes(1).set_seconds(3)));
    assert_eq!("1hr 0m 0s", format!("{}", Duration::new().set_hours(1)));
    assert_eq!("1dy 0hr 0m 0s", format!("{}", Duration::new().set_days(1)));
    assert_eq!("1wk 0dy 0hr 0m 0s", format!("{}", Duration::new().set_weeks(1)));
}

#[test]
fn test_parse_input() {
    // simple seconds
    assert_eq!(input2sec("10".to_string()), Ok(10));
    assert_eq!(input2sec("10s".to_string()), Ok(10));
    assert_eq!(input2sec("10 s".to_string()), Ok(10));
    assert_eq!(input2sec("10 sec".to_string()), Ok(10));
    assert_eq!(input2sec("10 foos".to_string()), Err("Invalid input".to_string()));

    // seconds with precision
    assert_eq!(input2sec("10.5".to_string()), Ok(10));
    assert_eq!(input2sec("10.5s".to_string()), Ok(10));
    assert_eq!(input2sec("10.2 s".to_string()), Ok(10));
    assert_eq!(input2sec("10.1 sec".to_string()), Ok(10));

    // minutes
    assert_eq!(input2sec("2m".to_string()), Ok(120));
    assert_eq!(input2sec("2m 20".to_string()), Ok(140));
    assert_eq!(input2sec("2m 20s".to_string()), Ok(140));
    assert_eq!(input2sec("2m20s".to_string()), Ok(140));
    assert_eq!(input2sec("   2 m   20  s   ".to_string()), Ok(140));
    assert_eq!(input2sec("2:20".to_string()), Ok(140));
    assert_eq!(input2sec("02:20".to_string()), Ok(140));
    assert_eq!(input2sec("100:00".to_string()), Ok(6000));

    assert_eq!(input2sec("10m12.123s".to_string()), Ok(612));

    // milliseconds
    assert_eq!(input2sec("2000ms".to_string()), Ok(2));
    assert_eq!(input2sec("2ms".to_string()), Ok(0));
    assert_eq!(input2sec("2000 milliseconds".to_string()), Ok(2));
    assert_eq!(input2sec("1500ms".to_string()), Ok(1));
    assert_eq!(input2sec("1100ms".to_string()), Ok(1));
    assert_eq!(input2sec("1999ms".to_string()), Ok(1));
    // Drop sub-millisecond precision
    assert_eq!(input2sec("1000.000ms".to_string()), Ok(1));
    assert_eq!(input2sec("1000.5ms".to_string()), Ok(1));
    assert_eq!(input2sec("1000.4ms".to_string()), Ok(1));
    assert_eq!(input2sec("1000.9ms".to_string()), Ok(1));

    // microseconds
    assert_eq!(input2sec("2000000microsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000μsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000 μs".to_string()), Ok(2));

    // nanoseconds
    assert_eq!(input2sec("2000000000ns".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 ns".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 nsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 nanosec".to_string()), Ok(2));
}

<commit_msg>feat: On parsing error, include problem string in Err output<commit_after>//
//    Copyright (C) 2015  Rory McCann
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU Affero General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU Affero General Public License for more details.
//
//    You should have received a copy of the GNU Affero General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

extern crate num;
extern crate regex;

use std::env;
use std::fmt;
use num::integer::{div_rem, Integer};
use regex::Regex;

struct Duration<T> {
    weeks: T,
    days: T,
    hours: T,
    minutes: T,
    seconds: T,
}

impl<T:Integer> Duration<T> {
    fn new() -> Duration<T> {
        Duration{ weeks: T::zero(), days: T::zero(), hours: T::zero(), minutes: T::zero(), seconds: T::zero() }
    }

    fn set_weeks(mut self, weeks: T) -> Duration<T> {
        self.weeks = weeks;
        self
    }
    fn set_days(mut self, days: T) -> Duration<T> {
        self.days = days;
        self
    }
    fn set_hours(mut self, hours: T) -> Duration<T> {
        self.hours = hours;
        self
    }
    fn set_minutes(mut self, minutes: T) -> Duration<T> {
        self.minutes = minutes;
        self
    }
    fn set_seconds(mut self, seconds: T) -> Duration<T> {
        self.seconds = seconds;
        self
    }

}

impl fmt::Display for Duration<u64> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut writing = false;
        if self.weeks != 0 {
            try!(write!(f, "{}wk", self.weeks));
            writing = true;
        }
        if self.days != 0 || writing {
            if writing { try!(write!(f, " ")); }
            try!(write!(f, "{}dy", self.days));
            writing = true;
        }
        if self.hours != 0 || writing {
            if writing { try!(write!(f, " ")); }
            try!(write!(f, "{}hr", self.hours));
            writing = true;
        }
        if self.minutes != 0 || writing {
            if writing { try!(write!(f, " ")); }
            try!(write!(f, "{}m", self.minutes));
            writing = true;
        }
        if self.seconds != 0 || writing {
            if writing { try!(write!(f, " ")); }
            try!(write!(f, "{}s", self.seconds));
            //writing = true;
        }
        Ok(())
    }
}

fn sec2duration(seconds: u64) -> Duration<u64> {
    let (minutes, seconds) = div_rem(seconds, 60);
    let (hours, minutes) = div_rem(minutes, 60);
    let (days, hours) = div_rem(hours, 24);
    let (weeks, days) = div_rem(days, 7);

    Duration::new().set_seconds(seconds).set_minutes(minutes).set_hours(hours).set_days(days).set_weeks(weeks)
}

// Converts a textual input to the number of seconds this represents. String error if something went wrong.
fn input2sec(input:String) -> Result<u64, String> {
    // TODO replace with regex! macro so the is guaranteed to be OK

    if let Some(cap) = Regex::new(r"^\s*(?P<sec>[0-9]+)(\.[0-9]+)?\s*(s|sec|seconds?)?\s*$").unwrap().captures(&input) {
        // Just numbers, interpret as seconds. Truncate the sub-seconds
        let sec: u64 = try!(try!(cap.name("sec").ok_or("0")).parse().or(Err("Invalid seconds")));
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<min>[0-9]+)\s*(m|min|minutes?)\s*((?P<sec>[0-9]+)(\.[0-9]+)?\s*(s|sec|seconds?)?)?\s*$").unwrap().captures(&input) {
        // XmYs. Truncate the subseconds
        let sec: u64 = try!(cap.name("sec").unwrap_or(&"0").parse::<u64>().or(Err("Invalid seconds")));
        let min: u64 = try!(cap.name("min").unwrap_or(&"0").parse::<u64>().or(Err("Invalid minutes")));
        Ok(min*60 + sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<min>[0-9]+):(?P<sec>[0-9][0-9])\s*$").unwrap().captures(&input) {
        // 0:00
        let sec: u64 = try!(cap.name("sec").unwrap_or(&"0").parse::<u64>().or(Err("Invalid seconds")));
        let min: u64 = try!(cap.name("min").unwrap_or(&"0").parse::<u64>().or(Err("Invalid minutes")));
        Ok(min*60 + sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)(\.[0-9]+)?\s*(ms|msec|milliseconds?)\s*$").unwrap().captures(&input) {
        // Milliseconds
        // Ignore trailing sub-milliseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid milliseconds")));
        let sec = ms / 1_000;
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)\s*(μs|μsec|microsec|microseconds?)\s*$").unwrap().captures(&input) {
        // Microseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid microseconds")));
        let sec = ms / 1_000_000;
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)\s*(ns|nsec|nanosec|nanoseconds?)\s*$").unwrap().captures(&input) {
        // Nanoseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid microseconds")));
        let sec = ms / 1_000_000_000;
        Ok(sec)
    } else {
        Err(format!("Invalid input: {}", input))
    }

}

fn prettytime(input: Vec<String>) -> Result<String, String> {
    if input.len() < 1 { return Err("No input".to_string()); }

    let input = input.join(" ");
    let seconds: u64 = try!(input2sec(input));

    let duration = sec2duration(seconds);

    Ok(format!("{}", duration))
}

fn main() {
    let args: Vec<_> = env::args().skip(1).collect();
    match prettytime(args) {
        Ok(s) => { println!("{}", s); },
        Err(s) => { println!("{}", s); std::process::exit(1); }
    }
}

#[test]
fn test_print_duration() {
    assert_eq!("", format!("{}", Duration::new()));
    assert_eq!("1s", format!("{}", Duration::new().set_seconds(1)));
    assert_eq!("1m 0s", format!("{}", Duration::new().set_minutes(1)));
    assert_eq!("1m 3s", format!("{}", Duration::new().set_minutes(1).set_seconds(3)));
    assert_eq!("1hr 0m 0s", format!("{}", Duration::new().set_hours(1)));
    assert_eq!("1dy 0hr 0m 0s", format!("{}", Duration::new().set_days(1)));
    assert_eq!("1wk 0dy 0hr 0m 0s", format!("{}", Duration::new().set_weeks(1)));
}

#[test]
fn test_parse_input() {
    // simple seconds
    assert_eq!(input2sec("10".to_string()), Ok(10));
    assert_eq!(input2sec("10s".to_string()), Ok(10));
    assert_eq!(input2sec("10 s".to_string()), Ok(10));
    assert_eq!(input2sec("10 sec".to_string()), Ok(10));
    assert_eq!(input2sec("10 foos".to_string()), Err("Invalid input: 10 foos".to_string()));

    // seconds with precision
    assert_eq!(input2sec("10.5".to_string()), Ok(10));
    assert_eq!(input2sec("10.5s".to_string()), Ok(10));
    assert_eq!(input2sec("10.2 s".to_string()), Ok(10));
    assert_eq!(input2sec("10.1 sec".to_string()), Ok(10));

    // minutes
    assert_eq!(input2sec("2m".to_string()), Ok(120));
    assert_eq!(input2sec("2m 20".to_string()), Ok(140));
    assert_eq!(input2sec("2m 20s".to_string()), Ok(140));
    assert_eq!(input2sec("2m20s".to_string()), Ok(140));
    assert_eq!(input2sec("   2 m   20  s   ".to_string()), Ok(140));
    assert_eq!(input2sec("2:20".to_string()), Ok(140));
    assert_eq!(input2sec("02:20".to_string()), Ok(140));
    assert_eq!(input2sec("100:00".to_string()), Ok(6000));

    assert_eq!(input2sec("10m12.123s".to_string()), Ok(612));

    // milliseconds
    assert_eq!(input2sec("2000ms".to_string()), Ok(2));
    assert_eq!(input2sec("2ms".to_string()), Ok(0));
    assert_eq!(input2sec("2000 milliseconds".to_string()), Ok(2));
    assert_eq!(input2sec("1500ms".to_string()), Ok(1));
    assert_eq!(input2sec("1100ms".to_string()), Ok(1));
    assert_eq!(input2sec("1999ms".to_string()), Ok(1));
    // Drop sub-millisecond precision
    assert_eq!(input2sec("1000.000ms".to_string()), Ok(1));
    assert_eq!(input2sec("1000.5ms".to_string()), Ok(1));
    assert_eq!(input2sec("1000.4ms".to_string()), Ok(1));
    assert_eq!(input2sec("1000.9ms".to_string()), Ok(1));

    // microseconds
    assert_eq!(input2sec("2000000microsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000μsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000 μs".to_string()), Ok(2));

    // nanoseconds
    assert_eq!(input2sec("2000000000ns".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 ns".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 nsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 nanosec".to_string()), Ok(2));
}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::sync::mpsc::channel;
use std::thread;

/// Compute the frequency of each letter (technically of each unicode codepoint) using the given
/// number of worker threads.
pub fn frequency(texts: &[&str], num_workers: usize) -> HashMap<char, usize> {
    assert!(num_workers > 0);
    let part_size_floor = texts.len() / num_workers;
    let rem = texts.len() % num_workers;
    let part_size = if rem > 0 {
        part_size_floor + 1
    } else {
        part_size_floor
    };
    let mut parts: Vec<Vec<String>> = Vec::with_capacity(part_size);
    for _ in 0..num_workers {
        parts.push(Vec::with_capacity(part_size));
    }
    let mut i = 0;
    for line in texts.iter() {
        // We'll need to clone those strings in order to satisfy some lifetime guarantees. Basically
        // it's hard for the system to be sure that the threads spawned don't outlive the strings.
        parts[i].push(line.to_string());
        i = (i + 1) % num_workers;
    }

    let (tx, rx) = channel();

    for part in parts {
        let tx = tx.clone();
        thread::spawn(move || {
            tx.send(count(part)).unwrap();
        });
    }

    let mut results: HashMap<char, usize> = HashMap::new();
    for _ in 0..num_workers {
        let part_results = rx.recv().unwrap();
        for (c, n) in part_results.into_iter() {
            *results.entry(c).or_insert(0) += n;
        }
    }
    results
}

fn count(lines: Vec<String>) -> HashMap<char, usize> {
    let mut results: HashMap<char, usize> = HashMap::new();
    for line in lines.iter() {
        for c in line.chars() {
            if c.is_alphabetic() {
                *results.entry(c.to_lowercase().next().unwrap()).or_insert(0) += 1;
            }
        }
    }
    results
}
<commit_msg>parallel-letter-frequency: Use `&[T]` instead of `Vec<T>`<commit_after>use std::collections::HashMap;
use std::sync::mpsc::channel;
use std::thread;

/// Compute the frequency of each letter (technically of each unicode codepoint) using the given
/// number of worker threads.
pub fn frequency(texts: &[&str], num_workers: usize) -> HashMap<char, usize> {
    assert!(num_workers > 0);
    let part_size_floor = texts.len() / num_workers;
    let rem = texts.len() % num_workers;
    let part_size = if rem > 0 {
        part_size_floor + 1
    } else {
        part_size_floor
    };
    let mut parts: Vec<Vec<String>> = Vec::with_capacity(part_size);
    for _ in 0..num_workers {
        parts.push(Vec::with_capacity(part_size));
    }
    let mut i = 0;
    for line in texts.iter() {
        // We'll need to clone those strings in order to satisfy some lifetime guarantees. Basically
        // it's hard for the system to be sure that the threads spawned don't outlive the strings.
        parts[i].push(line.to_string());
        i = (i + 1) % num_workers;
    }

    let (tx, rx) = channel();

    for part in parts {
        let tx = tx.clone();
        thread::spawn(move || {
            tx.send(count(&part)).unwrap();
        });
    }

    let mut results: HashMap<char, usize> = HashMap::new();
    for _ in 0..num_workers {
        let part_results = rx.recv().unwrap();
        for (c, n) in part_results.into_iter() {
            *results.entry(c).or_insert(0) += n;
        }
    }
    results
}

fn count(lines: &[String]) -> HashMap<char, usize> {
    let mut results: HashMap<char, usize> = HashMap::new();
    for line in lines.iter() {
        for c in line.chars() {
            if c.is_alphabetic() {
                *results.entry(c.to_lowercase().next().unwrap()).or_insert(0) += 1;
            }
        }
    }
    results
}
<|endoftext|>


<commit_before>//! The module contains an implementation of a simple HTTP/2 client.

use http::client::{ClientConnection, HttpConnect};
use http::session::{SessionState, DefaultSessionState};
use super::super::http::connection::HttpConnection;
use super::super::http::transport::TransportStream;
use super::super::http::session::Stream;
use super::super::http::{StreamId, HttpResult, HttpError, Response, Header, Request};

/// A struct implementing a simple HTTP/2 client.
///
/// This client works as an HTTP/1.1 client with a Keep-Alive connection and
/// pipelining might work.
///
/// Multiple requests can be queued up (and sent to the server) by calling
/// `request` multiple times, before any `get_response`.
///
/// Once a `get_response` is issued, the client blocks until it receives the
/// response for the particular request that was referenced in the `get_response`
/// call.
///
/// Therefore, by doing `request` -> `get_response` we can use the HTTP/2
/// connection as a `Keep-Alive` HTTP/1.1 connection and a pipelined flow by
/// queuing up a sequence of requests and then "joining" over them by calling
/// `get_response` for each of them.
///
/// The responses that are returned by the client are very raw representations
/// of the response.
///
/// # Notes
///
/// - For now (temporarily) no requests with bodies are supported.
/// - A direct HTTP/2 connection is used (not an upgrade of an HTTP/1.1
///   connection)
///
/// # Examples
///
/// Issue a simple GET request using the helper `get` method. Premade connection
/// passed to the client.
///
/// ```no_run
/// use std::net::TcpStream;
/// use solicit::http::HttpScheme;
/// use solicit::http::connection::HttpConnection;
/// use solicit::http::client::write_preface;
/// use solicit::client::SimpleClient;
/// use std::str;
///
/// // Prepare a stream manually... We must write the preface ourselves in this case.
/// // This is a more advanced way to use the client and the `HttpConnect` implementations
/// // should usually be preferred for their convenience.
/// let mut stream = TcpStream::connect(&("http2bin.org", 80)).unwrap();
/// write_preface(&mut stream);
/// // Connect to an HTTP/2 aware server
/// let conn = HttpConnection::<TcpStream, TcpStream>::with_stream(
///                                stream,
///                                HttpScheme::Http);
/// let mut client = SimpleClient::with_connection(conn, "http2bin.org".into()).unwrap();
/// let response = client.get(b"/", &[]).unwrap();
/// assert_eq!(response.stream_id, 1);
/// assert_eq!(response.status_code().unwrap(), 200);
/// // Dump the headers and the response body to stdout.
/// // They are returned as raw bytes for the user to do as they please.
/// // (Note: in general directly decoding assuming a utf8 encoding might not
/// // always work -- this is meant as a simple example that shows that the
/// // response is well formed.)
/// for header in response.headers.iter() {
///     println!("{}: {}",
///         str::from_utf8(&header.0).unwrap(),
///         str::from_utf8(&header.1).unwrap());
/// }
/// println!("{}", str::from_utf8(&response.body).unwrap());
/// ```
///
/// Issue a simple GET request using the helper `get` method. Pass a connector
/// to establish a new connection.
///
/// ```no_run
/// use solicit::http::client::CleartextConnector;
/// use solicit::client::SimpleClient;
/// use std::str;
///
/// // Connect to an HTTP/2 aware server
/// let connector = CleartextConnector { host: "http2bin.org" };
/// let mut client = SimpleClient::with_connector(connector).unwrap();
/// let response = client.get(b"/", &[]).unwrap();
/// assert_eq!(response.stream_id, 1);
/// assert_eq!(response.status_code().unwrap(), 200);
/// // Dump the headers and the response body to stdout.
/// // They are returned as raw bytes for the user to do as they please.
/// // (Note: in general directly decoding assuming a utf8 encoding might not
/// // always work -- this is meant as a simple example that shows that the
/// // response is well formed.)
/// for header in response.headers.iter() {
///     println!("{}: {}",
///         str::from_utf8(&header.0).unwrap(),
///         str::from_utf8(&header.1).unwrap());
/// }
/// println!("{}", str::from_utf8(&response.body).unwrap());
/// ```
///
/// Issue a GET request over `https` using the `TlsConnector`
///
/// ```no_run
/// use solicit::http::client::TlsConnector;
/// use solicit::client::SimpleClient;
/// use std::str;
///
/// // Connect to an HTTP/2 aware server
/// let path = "/path/to/certs.pem";
/// let connector = TlsConnector::new("http2bin.org", &path);
/// let mut client = SimpleClient::with_connector(connector).unwrap();
/// let response = client.get(b"/get", &[]).unwrap();
/// assert_eq!(response.stream_id, 1);
/// assert_eq!(response.status_code().unwrap(), 200);
/// // Dump the headers and the response body to stdout.
/// // They are returned as raw bytes for the user to do as they please.
/// // (Note: in general directly decoding assuming a utf8 encoding might not
/// // always work -- this is meant as a simple example that shows that the
/// // response is well formed.)
/// for header in response.headers.iter() {
///     println!("{}: {}",
///         str::from_utf8(&header.0).unwrap(),
///         str::from_utf8(&header.1).unwrap());
/// }
/// println!("{}", str::from_utf8(&response.body).unwrap());
/// ```
pub struct SimpleClient<S> where S: TransportStream {
    /// The underlying `ClientConnection` that the client uses
    conn: ClientConnection<S, S>,
    /// Holds the ID that can be assigned to the next stream to be opened by the
    /// client.
    next_stream_id: u32,
    /// The name of the host to which the client is connected to.
    host: Vec<u8>,
}

impl<S> SimpleClient<S> where S: TransportStream {
    /// Create a new `SimpleClient` instance that will use the given `HttpConnection`
    /// to communicate to the server.
    ///
    /// It assumes that the connection stream is initialized and will *not* automatically write the
    /// client preface.
    pub fn with_connection(conn: HttpConnection<S, S>, host: String)
            -> HttpResult<SimpleClient<S>> {
        let mut client = SimpleClient {
            conn: ClientConnection::with_connection(conn, DefaultSessionState::new()),
            next_stream_id: 1,
            host: host.as_bytes().to_vec(),
        };

        try!(client.init());

        Ok(client)
    }

    /// A convenience constructor that first tries to establish an HTTP/2
    /// connection by using the given connector instance (an implementation of
    /// the `HttpConnect` trait).
    ///
    /// # Panics
    ///
    /// Currently, it panics if the connector returns an error.
    pub fn with_connector<C>(connector: C) -> HttpResult<SimpleClient<S>>
            where C: HttpConnect<Stream=S> {
        let stream = connector.connect().ok().unwrap();
        let conn = HttpConnection::<S, S>::with_stream(stream.0, stream.1);
        SimpleClient::with_connection(conn, stream.2)
    }

    /// Internal helper method that performs the initialization of the client's
    /// connection.
    #[inline]
    fn init(&mut self) -> HttpResult<()> {
        self.conn.init()
    }

    /// Send a request to the server. Blocks until the entire request has been
    /// sent.
    ///
    /// The request is described by the method, the path on which it should be
    /// invoked and the "real" headers that should be included. Clients should
    /// never put pseudo-headers in the `headers` parameter, as those are
    /// automatically included based on metadata.
    ///
    /// # Returns
    ///
    /// If the full request is successfully sent, returns the ID of the stream
    /// on which the request was sent. Clients can use this ID to refer to the
    /// response.
    ///
    /// Any IO errors are propagated.
    pub fn request(&mut self, method: &[u8], path: &[u8], extras: &[Header], body: Option<Vec<u8>>)
            -> HttpResult<StreamId> {
        let stream_id = self.new_stream();
        let mut headers: Vec<Header> = vec![
            (b":method".to_vec(), method.to_vec()),
            (b":path".to_vec(), path.to_vec()),
            (b":authority".to_vec(), self.host.clone()),
            (b":scheme".to_vec(), self.conn.scheme().as_bytes().to_vec()),
        ];
        headers.extend(extras.to_vec().into_iter());

        try!(self.conn.send_request(Request {
            stream_id: stream_id,
            headers: headers,
            body: body.unwrap_or(Vec::new()),
        }));

        Ok(stream_id)
    }

    /// Gets the response for the stream with the given ID. If a valid stream ID
    /// is given, it blocks until a response is received.
    ///
    /// # Returns
    ///
    /// A `Response` if the response can be successfully read.
    ///
    /// Any underlying IO errors are propagated. Errors in the HTTP/2 protocol
    /// also stop processing and are returned to the client.
    pub fn get_response(&mut self, stream_id: StreamId) -> HttpResult<Response> {
        match self.conn.state.get_stream_ref(stream_id) {
            None => return Err(HttpError::UnknownStreamId),
            Some(_) => {},
        };
        loop {
            if let Some(stream) = self.conn.state.get_stream_ref(stream_id) {
                if stream.is_closed() {
                    return Ok(Response {
                        stream_id: stream.id(),
                        headers: stream.headers.clone().unwrap(),
                        body: stream.body.clone(),
                    });
                }
            }
            try!(self.handle_next_frame());
        }
    }

    /// Performs a GET request on the given path. This is a shortcut method for
    /// calling `request` followed by `get_response` for the returned stream ID.
    pub fn get(&mut self, path: &[u8], extra_headers: &[Header])
            -> HttpResult<Response> {
        let stream_id = try!(self.request(b"GET", path, extra_headers, None));
        self.get_response(stream_id)
    }

    /// Performs a POST request on the given path.
    pub fn post(&mut self, path: &[u8], extra_headers: &[Header], body: Vec<u8>)
            -> HttpResult<Response> {
        let stream_id = try!(self.request(b"POST", path, extra_headers, Some(body)));
        self.get_response(stream_id)
    }

    /// Internal helper method that initializes a new stream and returns its
    /// ID once done.
    fn new_stream(&mut self) -> StreamId {
        let stream_id = self.get_next_stream_id();
        self.conn.state.insert_stream(Stream::new(stream_id));

        stream_id
    }

    /// Internal helper method that gets the next valid stream ID number.
    fn get_next_stream_id(&mut self) -> StreamId {
        let ret = self.next_stream_id;
        self.next_stream_id += 2;

        ret
    }

    /// Internal helper method that triggers the client to handle the next
    /// frame off the HTTP/2 connection.
    #[inline]
    fn handle_next_frame(&mut self) -> HttpResult<()> {
        self.conn.handle_next_frame()
    }
}
<commit_msg>Refactor(client/simple): Use `start_request`<commit_after>//! The module contains an implementation of a simple HTTP/2 client.

use http::client::{ClientConnection, HttpConnect, SendStatus, RequestStream};
use http::session::{SessionState, DefaultSessionState, DefaultStream};
use super::super::http::connection::HttpConnection;
use super::super::http::transport::TransportStream;
use super::super::http::session::Stream;
use super::super::http::{StreamId, HttpResult, HttpError, Response, Header};

/// A struct implementing a simple HTTP/2 client.
///
/// This client works as an HTTP/1.1 client with a Keep-Alive connection and
/// pipelining might work.
///
/// Multiple requests can be queued up (and sent to the server) by calling
/// `request` multiple times, before any `get_response`.
///
/// Once a `get_response` is issued, the client blocks until it receives the
/// response for the particular request that was referenced in the `get_response`
/// call.
///
/// Therefore, by doing `request` -> `get_response` we can use the HTTP/2
/// connection as a `Keep-Alive` HTTP/1.1 connection and a pipelined flow by
/// queuing up a sequence of requests and then "joining" over them by calling
/// `get_response` for each of them.
///
/// The responses that are returned by the client are very raw representations
/// of the response.
///
/// # Notes
///
/// - For now (temporarily) no requests with bodies are supported.
/// - A direct HTTP/2 connection is used (not an upgrade of an HTTP/1.1
///   connection)
///
/// # Examples
///
/// Issue a simple GET request using the helper `get` method. Premade connection
/// passed to the client.
///
/// ```no_run
/// use std::net::TcpStream;
/// use solicit::http::HttpScheme;
/// use solicit::http::connection::HttpConnection;
/// use solicit::http::client::write_preface;
/// use solicit::client::SimpleClient;
/// use std::str;
///
/// // Prepare a stream manually... We must write the preface ourselves in this case.
/// // This is a more advanced way to use the client and the `HttpConnect` implementations
/// // should usually be preferred for their convenience.
/// let mut stream = TcpStream::connect(&("http2bin.org", 80)).unwrap();
/// write_preface(&mut stream);
/// // Connect to an HTTP/2 aware server
/// let conn = HttpConnection::<TcpStream, TcpStream>::with_stream(
///                                stream,
///                                HttpScheme::Http);
/// let mut client = SimpleClient::with_connection(conn, "http2bin.org".into()).unwrap();
/// let response = client.get(b"/", &[]).unwrap();
/// assert_eq!(response.stream_id, 1);
/// assert_eq!(response.status_code().unwrap(), 200);
/// // Dump the headers and the response body to stdout.
/// // They are returned as raw bytes for the user to do as they please.
/// // (Note: in general directly decoding assuming a utf8 encoding might not
/// // always work -- this is meant as a simple example that shows that the
/// // response is well formed.)
/// for header in response.headers.iter() {
///     println!("{}: {}",
///         str::from_utf8(&header.0).unwrap(),
///         str::from_utf8(&header.1).unwrap());
/// }
/// println!("{}", str::from_utf8(&response.body).unwrap());
/// ```
///
/// Issue a simple GET request using the helper `get` method. Pass a connector
/// to establish a new connection.
///
/// ```no_run
/// use solicit::http::client::CleartextConnector;
/// use solicit::client::SimpleClient;
/// use std::str;
///
/// // Connect to an HTTP/2 aware server
/// let connector = CleartextConnector { host: "http2bin.org" };
/// let mut client = SimpleClient::with_connector(connector).unwrap();
/// let response = client.get(b"/", &[]).unwrap();
/// assert_eq!(response.stream_id, 1);
/// assert_eq!(response.status_code().unwrap(), 200);
/// // Dump the headers and the response body to stdout.
/// // They are returned as raw bytes for the user to do as they please.
/// // (Note: in general directly decoding assuming a utf8 encoding might not
/// // always work -- this is meant as a simple example that shows that the
/// // response is well formed.)
/// for header in response.headers.iter() {
///     println!("{}: {}",
///         str::from_utf8(&header.0).unwrap(),
///         str::from_utf8(&header.1).unwrap());
/// }
/// println!("{}", str::from_utf8(&response.body).unwrap());
/// ```
///
/// Issue a GET request over `https` using the `TlsConnector`
///
/// ```no_run
/// use solicit::http::client::TlsConnector;
/// use solicit::client::SimpleClient;
/// use std::str;
///
/// // Connect to an HTTP/2 aware server
/// let path = "/path/to/certs.pem";
/// let connector = TlsConnector::new("http2bin.org", &path);
/// let mut client = SimpleClient::with_connector(connector).unwrap();
/// let response = client.get(b"/get", &[]).unwrap();
/// assert_eq!(response.stream_id, 1);
/// assert_eq!(response.status_code().unwrap(), 200);
/// // Dump the headers and the response body to stdout.
/// // They are returned as raw bytes for the user to do as they please.
/// // (Note: in general directly decoding assuming a utf8 encoding might not
/// // always work -- this is meant as a simple example that shows that the
/// // response is well formed.)
/// for header in response.headers.iter() {
///     println!("{}: {}",
///         str::from_utf8(&header.0).unwrap(),
///         str::from_utf8(&header.1).unwrap());
/// }
/// println!("{}", str::from_utf8(&response.body).unwrap());
/// ```
pub struct SimpleClient<S> where S: TransportStream {
    /// The underlying `ClientConnection` that the client uses
    conn: ClientConnection<S, S>,
    /// Holds the ID that can be assigned to the next stream to be opened by the
    /// client.
    next_stream_id: u32,
    /// The name of the host to which the client is connected to.
    host: Vec<u8>,
}

impl<S> SimpleClient<S> where S: TransportStream {
    /// Create a new `SimpleClient` instance that will use the given `HttpConnection`
    /// to communicate to the server.
    ///
    /// It assumes that the connection stream is initialized and will *not* automatically write the
    /// client preface.
    pub fn with_connection(conn: HttpConnection<S, S>, host: String)
            -> HttpResult<SimpleClient<S>> {
        let mut client = SimpleClient {
            conn: ClientConnection::with_connection(conn, DefaultSessionState::new()),
            next_stream_id: 1,
            host: host.as_bytes().to_vec(),
        };

        try!(client.init());

        Ok(client)
    }

    /// A convenience constructor that first tries to establish an HTTP/2
    /// connection by using the given connector instance (an implementation of
    /// the `HttpConnect` trait).
    ///
    /// # Panics
    ///
    /// Currently, it panics if the connector returns an error.
    pub fn with_connector<C>(connector: C) -> HttpResult<SimpleClient<S>>
            where C: HttpConnect<Stream=S> {
        let stream = connector.connect().ok().unwrap();
        let conn = HttpConnection::<S, S>::with_stream(stream.0, stream.1);
        SimpleClient::with_connection(conn, stream.2)
    }

    /// Internal helper method that performs the initialization of the client's
    /// connection.
    #[inline]
    fn init(&mut self) -> HttpResult<()> {
        self.conn.init()
    }

    /// Send a request to the server. Blocks until the entire request has been
    /// sent.
    ///
    /// The request is described by the method, the path on which it should be
    /// invoked and the "real" headers that should be included. Clients should
    /// never put pseudo-headers in the `headers` parameter, as those are
    /// automatically included based on metadata.
    ///
    /// # Returns
    ///
    /// If the full request is successfully sent, returns the ID of the stream
    /// on which the request was sent. Clients can use this ID to refer to the
    /// response.
    ///
    /// Any IO errors are propagated.
    pub fn request(&mut self, method: &[u8], path: &[u8], extras: &[Header], body: Option<Vec<u8>>)
            -> HttpResult<StreamId> {
        // Prepares the request stream
        let stream = self.new_stream(method, path, extras, body);
        // Remember the stream's ID before passing on the ownership to the connection
        let stream_id = stream.stream.id();
        // Starts the request (i.e. sends out the headers)
        try!(self.conn.start_request(stream));

        // And now makes sure the data is sent out...
        // Note: Since for now there is no flow control, sending data will always continue
        //       progressing, but it might violate flow control windows, causing the peer to shut
        //       down the connection.
        debug!("Trying to send the body");
        while let SendStatus::Sent = try!(self.conn.send_next_data()) {
            // We iterate until the data is sent, as the contract of this call is that it blocks
            // until such a time.
        }

        Ok(stream_id)
    }

    /// Gets the response for the stream with the given ID. If a valid stream ID
    /// is given, it blocks until a response is received.
    ///
    /// # Returns
    ///
    /// A `Response` if the response can be successfully read.
    ///
    /// Any underlying IO errors are propagated. Errors in the HTTP/2 protocol
    /// also stop processing and are returned to the client.
    pub fn get_response(&mut self, stream_id: StreamId) -> HttpResult<Response> {
        match self.conn.state.get_stream_ref(stream_id) {
            None => return Err(HttpError::UnknownStreamId),
            Some(_) => {},
        };
        loop {
            if let Some(stream) = self.conn.state.get_stream_ref(stream_id) {
                if stream.is_closed() {
                    return Ok(Response {
                        stream_id: stream.id(),
                        headers: stream.headers.clone().unwrap(),
                        body: stream.body.clone(),
                    });
                }
            }
            try!(self.handle_next_frame());
        }
    }

    /// Performs a GET request on the given path. This is a shortcut method for
    /// calling `request` followed by `get_response` for the returned stream ID.
    pub fn get(&mut self, path: &[u8], extra_headers: &[Header])
            -> HttpResult<Response> {
        let stream_id = try!(self.request(b"GET", path, extra_headers, None));
        self.get_response(stream_id)
    }

    /// Performs a POST request on the given path.
    pub fn post(&mut self, path: &[u8], extra_headers: &[Header], body: Vec<u8>)
            -> HttpResult<Response> {
        let stream_id = try!(self.request(b"POST", path, extra_headers, Some(body)));
        self.get_response(stream_id)
    }

    /// Internal helper method that prepares a new `RequestStream` instance based on the given
    /// request parameters.
    ///
    /// The `RequestStream` is then ready to be passed on to the connection instance in order to
    /// start the request.
    fn new_stream(&mut self, method: &[u8], path: &[u8], extras: &[Header], body: Option<Vec<u8>>)
            -> RequestStream<DefaultStream> {
        let stream_id = self.get_next_stream_id();
        let mut stream = DefaultStream::new(stream_id);
        match body {
            Some(body) => stream.set_full_data(body),
            None => stream.close_local(),
        };

        let mut headers: Vec<Header> = vec![
            (b":method".to_vec(), method.to_vec()),
            (b":path".to_vec(), path.to_vec()),
            (b":authority".to_vec(), self.host.clone()),
            (b":scheme".to_vec(), self.conn.scheme().as_bytes().to_vec()),
        ];
        headers.extend(extras.to_vec().into_iter());

        RequestStream {
            headers: headers,
            stream: stream,
        }
    }

    /// Internal helper method that gets the next valid stream ID number.
    fn get_next_stream_id(&mut self) -> StreamId {
        let ret = self.next_stream_id;
        self.next_stream_id += 2;

        ret
    }

    /// Internal helper method that triggers the client to handle the next
    /// frame off the HTTP/2 connection.
    #[inline]
    fn handle_next_frame(&mut self) -> HttpResult<()> {
        self.conn.handle_next_frame()
    }
}
<|endoftext|>


<commit_before>use num::{Signed, Unsigned};
use approx::Approx;

#[inline(always)]
pub fn inverse<'a, 'b, T: Signed>(out: &'a mut [T; 3], a: &'b [T; 3]) -> &'a mut [T; 3] {
    out[0] = -a[0];
    out[1] = -a[1];
    out[2] = -a[2];
    out
}
#[test]
fn test_inverse() {
    let mut v = [0, 0, 0];
    inverse(&mut v, &[1, 1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == -1);
    assert!(v[2] == -1);
}

#[inline(always)]
pub fn lerp<'a, 'b, T: Unsigned, N: Unsigned>(out: &'a mut [T; 3], a: &'b [T; 3], b: &'b [T; 3], t: N) -> &'a mut [T; 3] {
    let t_f64 = t.to_f64();
    out[0] = T::from_f64((a[0] + (b[0] - a[0])).to_f64() * t_f64);
    out[1] = T::from_f64((a[1] + (b[1] - a[1])).to_f64() * t_f64);
    out[2] = T::from_f64((a[2] + (b[2] - a[2])).to_f64() * t_f64);
    out
}
#[test]
fn test_lerp() {
    let mut v = [0, 0, 0];
    lerp(&mut v, &[0, 0, 0], &[2, 2, 2], 0.5);
    assert_eq!(v[0], 1);
    assert_eq!(v[1], 1);
    assert_eq!(v[2], 1);
}

#[inline(always)]
pub fn min<'a, 'b, T: Unsigned>(out: &'a mut [T; 3], a: &'b [T; 3], b: &'b [T; 3]) -> &'a mut [T; 3] {
    out[0] = if b[0] < a[0] {b[0]} else {a[0]};
    out[1] = if b[1] < a[1] {b[1]} else {a[1]};
    out[2] = if b[2] < a[2] {b[2]} else {a[2]};
    out
}
#[test]
fn test_min() {
    let mut v = [0, 0, 0];
    min(&mut v, &[1, 0, 1], &[0, 1, 0]);
    assert!(v == [0, 0, 0]);
}

#[inline(always)]
pub fn max<'a, 'b, T: Unsigned>(out: &'a mut [T; 3], a: &'b [T; 3], b: &'b [T; 3]) -> &'a mut [T; 3] {
    out[0] = if b[0] > a[0] {b[0]} else {a[0]};
    out[1] = if b[1] > a[1] {b[1]} else {a[1]};
    out[2] = if b[2] > a[2] {b[2]} else {a[2]};
    out
}
#[test]
fn test_max() {
    let mut v = [0, 0, 0];
    max(&mut v, &[1, 0, 1], &[0, 1, 0]);
    assert!(v == [1, 1, 1]);
}

#[inline(always)]
pub fn clamp<'a, 'b, T: Unsigned>(out: &'a mut [T; 3], a: &'b [T; 3], min: &'b [T; 3], max: &'b [T; 3]) -> &'a mut [T; 3] {
    out[0] = if a[0] < min[0] {min[0]} else if a[0] > max[0] {max[0]} else {a[0]};
    out[1] = if a[1] < min[1] {min[1]} else if a[1] > max[1] {max[1]} else {a[1]};
    out[2] = if a[2] < min[2] {min[2]} else if a[2] > max[2] {max[2]} else {a[2]};
    out
}
#[test]
fn test_clamp() {
    let mut v = [0, 0, 0];
    clamp(&mut v, &[2, 2, 2], &[0, 0, 0], &[1, 1, 1]);
    assert!(v == [1, 1, 1]);
}

#[inline(always)]
pub fn eq<'a, T: Unsigned>(a: &'a [T; 3], b: &'a [T; 3]) -> bool {
    !ne(a, b)
}
#[test]
fn test_eq() {
    assert_eq!(eq(&[1f32, 1f32, 1f32], &[1f32, 1f32, 1f32]), true);
    assert_eq!(eq(&[0f32, 0f32, 0f32], &[1f32, 1f32, 1f32]), false);
}

#[inline(always)]
pub fn ne<'a, T: Unsigned>(a: &'a [T; 3], b: &'a [T; 3]) -> bool {
    !a[0].approx_eq(b[0]) ||
    !a[1].approx_eq(b[1]) ||
    !a[2].approx_eq(b[2])
}
#[test]
fn test_ne() {
    assert_eq!(ne(&[1f32, 1f32, 1f32], &[1f32, 1f32, 1f32]), false);
    assert_eq!(ne(&[0f32, 0f32, 0f32], &[1f32, 1f32, 1f32]), true);
}
<commit_msg>clean up<commit_after>use num::{Signed, Unsigned};
use approx::Approx;

#[inline(always)]
pub fn inverse<'a, 'b, T: Signed>(out: &'a mut [T; 3], a: &'b [T; 3]) -> &'a mut [T; 3] {
    out[0] = -a[0];
    out[1] = -a[1];
    out[2] = -a[2];
    out
}
#[test]
fn test_inverse() {
    let mut v = [0, 0, 0];
    inverse(&mut v, &[1, 1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == -1);
    assert!(v[2] == -1);
}

#[inline(always)]
pub fn lerp<'a, 'b, T: Unsigned, N: Unsigned>(out: &'a mut [T; 3], a: &'b [T; 3], b: &'b [T; 3], t: N) -> &'a mut [T; 3] {
    let t_f64 = t.to_f64();
    out[0] = T::from_f64((a[0] + (b[0] - a[0])).to_f64() * t_f64);
    out[1] = T::from_f64((a[1] + (b[1] - a[1])).to_f64() * t_f64);
    out[2] = T::from_f64((a[2] + (b[2] - a[2])).to_f64() * t_f64);
    out
}
#[test]
fn test_lerp() {
    let mut v = [0, 0, 0];
    lerp(&mut v, &[0, 0, 0], &[2, 2, 2], 0.5);
    assert_eq!(v[0], 1);
    assert_eq!(v[1], 1);
    assert_eq!(v[2], 1);
}

#[inline(always)]
pub fn min<'a, 'b, T: Unsigned>(out: &'a mut [T; 3], a: &'b [T; 3], b: &'b [T; 3]) -> &'a mut [T; 3] {
    out[0] = if b[0] < a[0] {b[0]} else {a[0]};
    out[1] = if b[1] < a[1] {b[1]} else {a[1]};
    out[2] = if b[2] < a[2] {b[2]} else {a[2]};
    out
}
#[test]
fn test_min() {
    let mut v = [0, 0, 0];
    min(&mut v, &[1, 0, 1], &[0, 1, 0]);
    assert!(v == [0, 0, 0]);
}

#[inline(always)]
pub fn max<'a, 'b, T: Unsigned>(out: &'a mut [T; 3], a: &'b [T; 3], b: &'b [T; 3]) -> &'a mut [T; 3] {
    out[0] = if b[0] > a[0] {b[0]} else {a[0]};
    out[1] = if b[1] > a[1] {b[1]} else {a[1]};
    out[2] = if b[2] > a[2] {b[2]} else {a[2]};
    out
}
#[test]
fn test_max() {
    let mut v = [0, 0, 0];
    max(&mut v, &[1, 0, 1], &[0, 1, 0]);
    assert!(v == [1, 1, 1]);
}

#[inline(always)]
pub fn clamp<'a, 'b, T: Unsigned>(out: &'a mut [T; 3], a: &'b [T; 3], min: &'b [T; 3], max: &'b [T; 3]) -> &'a mut [T; 3] {
    out[0] = if a[0] < min[0] {min[0]} else if a[0] > max[0] {max[0]} else {a[0]};
    out[1] = if a[1] < min[1] {min[1]} else if a[1] > max[1] {max[1]} else {a[1]};
    out[2] = if a[2] < min[2] {min[2]} else if a[2] > max[2] {max[2]} else {a[2]};
    out
}
#[test]
fn test_clamp() {
    let mut v = [0, 0, 0];
    clamp(&mut v, &[2, 2, 2], &[0, 0, 0], &[1, 1, 1]);
    assert!(v == [1, 1, 1]);
}

#[inline(always)]
pub fn eq<'a, T: Unsigned>(a: &'a [T; 3], b: &'a [T; 3]) -> bool {
    !ne(a, b)
}
#[test]
fn test_eq() {
    assert_eq!(eq(&[1f32, 1f32, 1f32], &[1f32, 1f32, 1f32]), true);
    assert_eq!(eq(&[0f32, 0f32, 0f32], &[1f32, 1f32, 1f32]), false);
}

#[inline(always)]
pub fn ne<'a, T: Unsigned>(a: &'a [T; 3], b: &'a [T; 3]) -> bool {
    !Approx::approx_eq(a[0], b[0]) ||
    !Approx::approx_eq(a[1], b[1]) ||
    !Approx::approx_eq(a[2], b[2])
}
#[test]
fn test_ne() {
    assert_eq!(ne(&[1f32, 1f32, 1f32], &[1f32, 1f32, 1f32]), false);
    assert_eq!(ne(&[0f32, 0f32, 0f32], &[1f32, 1f32, 1f32]), true);
}
<|endoftext|>


<commit_before><commit_msg>Add preliminary topology checks<commit_after><|endoftext|>


<commit_before><commit_msg>Healthy dose of `clippy`<commit_after><|endoftext|>


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


<commit_before><commit_msg>remove debugging<commit_after><|endoftext|>


<commit_before><commit_msg>Flag for not doing recursive spot checks<commit_after><|endoftext|>


<commit_before>// #![deny(missing_docs,
//         missing_debug_implementations, missing_copy_implementations,
//         trivial_casts, trivial_numeric_casts,
//         unsafe_code,
//         unstable_features,
//         unused_import_braces, unused_qualifications)]
extern crate rustc_serialize;

mod pokemon {

    #[derive(RustcDecodable, RustcEncodable)]
    pub struct Pokemon (Vec<String>);

    #[allow(dead_code, unused_variables)]
    pub fn get_pokemon() -> Pokemon {
        use std::fs::File;
        use rustc_serialize::json::decode;

        let mut file = File::open("data/en.json").unwrap();
        let mut data = String::new();

        let json: Pokemon = decode(&data).unwrap();

        json
    }

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

    }

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

    }

    #[allow(dead_code, unused_variables)]
    fn get_name(id: i32) {

    }
}
<commit_msg>init project<commit_after>// #![deny(missing_docs,
//         missing_debug_implementations, missing_copy_implementations,
//         trivial_casts, trivial_numeric_casts,
//         unsafe_code,
//         unstable_features,
//         unused_import_braces, unused_qualifications)]
extern crate rustc_serialize;

mod pokemon {

    #[derive(RustcDecodable, RustcEncodable)]
    pub struct Pokemon (Vec<String>);

    #[allow(dead_code, unused_mut, unused_variables)]
    pub fn get_pokemon() -> Pokemon {
        use std::fs::File;
        use rustc_serialize::json::decode;

        let mut file = File::open("data/en.json").unwrap();
        let mut data = String::new();

        let json: Pokemon = decode(&data).unwrap();

        json
    }

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

    }

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

    }

    #[allow(dead_code, unused_variables)]
    fn get_name(id: i32) {

    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate regex;

use std::collections::HashMap;

use hyper::method::Method;
use hyper::server::{Handler, Request, Response};
use hyper::status::StatusCode;
use regex::{Regex, RegexSet};

pub use error::RouterError;

pub type Captures = Option<Vec<String>>;
pub type NotFoundFn = fn(Request, Response);

#[derive(PartialEq, Eq, Hash)]
pub struct RouteInfo {
    route: String,
    verb: Method
}

/// The Router struct contains the information for your app to route requests
/// properly based on their HTTP method and matching route. It allows the use
/// of a custom 404 handler if desired but provides a default as well.
///
/// Under the hood a Router uses a RegexSet to match URI's that come in to the
/// instance of the hyper server. Because of this, it has the potential to match
/// multiple patterns that you provide. It will call the first handler that it
/// matches against so the order in which you add routes matters.
pub struct Router {
    /// A custom 404 handler that you can provide.
    pub not_found: Option<NotFoundFn>,

    routes: Option<RegexSet>,
    route_list: Vec<String>,
    compiled_list: Vec<Regex>,
    route_map: HashMap<RouteInfo, Box<Fn(Request, Response, Captures)>>
}

// These are needed to satisfy the Handler trait while using Fn to accept closures.
unsafe impl Send for Router { }
unsafe impl Sync for Router { }

impl Handler for Router {
    // The handle method for the router simply tries to match the URI against
    // the first pattern that it can which in turn calls its associated handle
    // function passing the hyper Request and Response structures.
    fn handle(&self, req: Request, res: Response) {
        let uri = format!("{}", req.uri);
        let matches = self.routes.as_ref().unwrap().matches(&uri);
        let index = matches.iter().next();
        match index {
            Some(i) => {
                let route = &self.route_list[i];
                let route_info = RouteInfo{route: route.clone(), verb: req.method.clone()};
                let handler = self.route_map.get(&route_info);
                match handler {
                    Some(h) => {
                        let compiled_pattern = &self.compiled_list[i];
                        let captures = get_captures(compiled_pattern, &uri);
                        h(req, res, captures);
                    }
                    None => {
                        not_allowed(req, res);
                    }
                }
            },
            None => self.not_found.unwrap()(req, res)
        }
    }
}

impl Router {
    /// Construct a new Router to maintain the routes and their handler
    /// functions.
    pub fn new() -> Router {
        Router {
            not_found: None,
            routes: None,
            route_list: Vec::new(),
            compiled_list: Vec::new(),
            route_map: HashMap::new(),
        }
    }

    /// Add a route to the router and give it a function to call when the route
    /// is matched against. You can call this explicitly or use the convenience
    /// methods defined below.
    pub fn add_route<H>(&mut self, verb: Method, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        let route_info = RouteInfo{route: route.to_owned(), verb: verb};
        let pattern = Regex::new(route);
        match pattern {
            Ok(p) => { self.compiled_list.push(p); },
            Err(e) => { println!("Not adding this route due to error: {}", e); }
        }
        self.route_list.push(route.to_owned());
        self.route_map.insert(route_info, Box::new(handler));
    }

    /// A convenience method for OPTIONS requests.
    pub fn options<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Options, route, handler);
    }

    /// A convenience method for GET requests.
    pub fn get<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Get, route, handler);
    }

    /// A convenience method for POST requests.
    pub fn post<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Post, route, handler);
    }

    /// A convenience method for PUT requests.
    pub fn put<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Put, route, handler);
    }

    /// A convenience method for DELETE requests.
    pub fn delete<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Delete, route, handler);
    }

    /// A convenience method for PATCH requests.
    pub fn patch<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Patch, route, handler);
    }

    /// This function ensures that a valid `RegexSet` could be made from the route
    /// vector that was built while using the functions that add routes. It
    /// requires that there exist at least one route so that the RegexSet can be
    /// successfully constructed.
    ///
    /// It will also ensure that there is a handler for routes that do not match
    /// any available in the set.
    pub fn finalize(&mut self) -> Result<(), RouterError> {
        if self.route_list.len() == 0  {
            return Err(RouterError::TooFewRoutes);
        }

        // Check if the user added a 404 handler, else use the default.
        match self.not_found {
            Some(_) => {},
            None => { self.not_found = Some(default_not_found); }
        }

        let re_routes = RegexSet::new(self.route_list.iter());
        match re_routes {
            Ok(r) => {
                self.routes = Some(r);
                Ok(())
            }
            Err(_) => {
                Err(RouterError::BadSet)
            }
        }
    }

    /// Add a function to handle routes that get no matches.
    pub fn add_not_found(&mut self, not_found: NotFoundFn) {
        self.not_found = Some(not_found)
    }
}

// The default 404 handler.
fn default_not_found(req: Request, mut res: Response) {
    let message = format!("No route handler found for {}", req.uri);
    *res.status_mut() = StatusCode::NotFound;
    res.send(message.as_bytes()).unwrap();
}

// This handler will get fired when a URI matches a route but contains the wrong method.
fn not_allowed(_: Request, mut res: Response) {
    *res.status_mut() = StatusCode::MethodNotAllowed;
    let res = res.start().unwrap();
    res.end().unwrap();
}

// Return that captures from a pattern that was matched.
fn get_captures(pattern: &Regex, uri: &str) -> Captures {
    // We know this compiles because it was part of the set.
    let caps = pattern.captures(uri);
    match caps {
        Some(caps) => {
            let mut v = vec![];
            for c in caps.iter() {
                v.push(c.unwrap().to_owned());
            }
            Some(v)
        },
        None => None
    }
}

mod error;

#[test]
fn no_routes() {
    let mut router = Router::new();
    let e = router.finalize();
    assert_eq!(e.err(), Some(RouterError::TooFewRoutes));
}

#[test]
fn bad_regular_expression() {
    fn test_handler(_: Request, _: Response, _: Captures) {}
    let mut router = Router::new();
    router.add_route(Method::Get, r"/[", test_handler);
    let e = router.finalize();
    assert_eq!(e.err(), Some(RouterError::BadSet));
}
<commit_msg>add anchor to provide better matching<commit_after>extern crate hyper;
extern crate regex;

use std::collections::HashMap;

use hyper::method::Method;
use hyper::server::{Handler, Request, Response};
use hyper::status::StatusCode;
use regex::{Regex, RegexSet};

pub use error::RouterError;

pub type Captures = Option<Vec<String>>;
pub type NotFoundFn = fn(Request, Response);

#[derive(PartialEq, Eq, Hash)]
pub struct RouteInfo {
    route: String,
    verb: Method
}

/// The Router struct contains the information for your app to route requests
/// properly based on their HTTP method and matching route. It allows the use
/// of a custom 404 handler if desired but provides a default as well.
///
/// Under the hood a Router uses a RegexSet to match URI's that come in to the
/// instance of the hyper server. Because of this, it has the potential to match
/// multiple patterns that you provide. It will call the first handler that it
/// matches against so the order in which you add routes matters.
pub struct Router {
    /// A custom 404 handler that you can provide.
    pub not_found: Option<NotFoundFn>,

    routes: Option<RegexSet>,
    route_list: Vec<String>,
    compiled_list: Vec<Regex>,
    route_map: HashMap<RouteInfo, Box<Fn(Request, Response, Captures)>>
}

// These are needed to satisfy the Handler trait while using Fn to accept closures.
unsafe impl Send for Router { }
unsafe impl Sync for Router { }

impl Handler for Router {
    // The handle method for the router simply tries to match the URI against
    // the first pattern that it can which in turn calls its associated handle
    // function passing the hyper Request and Response structures.
    fn handle(&self, req: Request, res: Response) {
        let uri = format!("{}", req.uri);
        let matches = self.routes.as_ref().unwrap().matches(&uri);
        let index = matches.iter().next();
        match index {
            Some(i) => {
                let route = &self.route_list[i];
                let route_info = RouteInfo{route: route.clone(), verb: req.method.clone()};
                let handler = self.route_map.get(&route_info);
                match handler {
                    Some(h) => {
                        let compiled_pattern = &self.compiled_list[i];
                        let captures = get_captures(compiled_pattern, &uri);
                        h(req, res, captures);
                    }
                    None => {
                        not_allowed(req, res);
                    }
                }
            },
            None => self.not_found.unwrap()(req, res)
        }
    }
}

impl Router {
    /// Construct a new Router to maintain the routes and their handler
    /// functions.
    pub fn new() -> Router {
        Router {
            not_found: None,
            routes: None,
            route_list: Vec::new(),
            compiled_list: Vec::new(),
            route_map: HashMap::new(),
        }
    }

    /// Add a route to the router and give it a function to call when the route
    /// is matched against. You can call this explicitly or use the convenience
    /// methods defined below.
    pub fn add_route<H>(&mut self, verb: Method, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        // This is added to provide stricter matching for routes that could have more than one
        // match.
        let anchored_pattern = [r"\A", route].join("");
        let route_info = RouteInfo{route: anchored_pattern.clone(), verb: verb};
        let pattern = Regex::new(&anchored_pattern);
        match pattern {
            Ok(p) => { self.compiled_list.push(p); },
            Err(e) => { println!("Not adding this route due to error: {}", e); }
        }
        self.route_list.push(anchored_pattern.clone());
        self.route_map.insert(route_info, Box::new(handler));
    }

    /// A convenience method for OPTIONS requests.
    pub fn options<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Options, route, handler);
    }

    /// A convenience method for GET requests.
    pub fn get<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Get, route, handler);
    }

    /// A convenience method for POST requests.
    pub fn post<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Post, route, handler);
    }

    /// A convenience method for PUT requests.
    pub fn put<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Put, route, handler);
    }

    /// A convenience method for DELETE requests.
    pub fn delete<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Delete, route, handler);
    }

    /// A convenience method for PATCH requests.
    pub fn patch<H>(&mut self, route: &str, handler: H)
        where H: Fn(Request, Response, Captures) + Send + Sync + 'static {
        self.add_route(Method::Patch, route, handler);
    }

    /// This function ensures that a valid `RegexSet` could be made from the route
    /// vector that was built while using the functions that add routes. It
    /// requires that there exist at least one route so that the RegexSet can be
    /// successfully constructed.
    ///
    /// It will also ensure that there is a handler for routes that do not match
    /// any available in the set.
    pub fn finalize(&mut self) -> Result<(), RouterError> {
        if self.route_list.len() == 0  {
            return Err(RouterError::TooFewRoutes);
        }

        // Check if the user added a 404 handler, else use the default.
        match self.not_found {
            Some(_) => {},
            None => { self.not_found = Some(default_not_found); }
        }

        let re_routes = RegexSet::new(self.route_list.iter());
        match re_routes {
            Ok(r) => {
                self.routes = Some(r);
                Ok(())
            }
            Err(_) => {
                Err(RouterError::BadSet)
            }
        }
    }

    /// Add a function to handle routes that get no matches.
    pub fn add_not_found(&mut self, not_found: NotFoundFn) {
        self.not_found = Some(not_found)
    }
}

// The default 404 handler.
fn default_not_found(req: Request, mut res: Response) {
    let message = format!("No route handler found for {}", req.uri);
    *res.status_mut() = StatusCode::NotFound;
    res.send(message.as_bytes()).unwrap();
}

// This handler will get fired when a URI matches a route but contains the wrong method.
fn not_allowed(_: Request, mut res: Response) {
    *res.status_mut() = StatusCode::MethodNotAllowed;
    let res = res.start().unwrap();
    res.end().unwrap();
}

// Return that captures from a pattern that was matched.
fn get_captures(pattern: &Regex, uri: &str) -> Captures {
    // We know this compiles because it was part of the set.
    let caps = pattern.captures(uri);
    match caps {
        Some(caps) => {
            let mut v = vec![];
            for c in caps.iter() {
                v.push(c.unwrap().to_owned());
            }
            Some(v)
        },
        None => None
    }
}

mod error;

#[test]
fn no_routes() {
    let mut router = Router::new();
    let e = router.finalize();
    assert_eq!(e.err(), Some(RouterError::TooFewRoutes));
}

#[test]
fn bad_regular_expression() {
    fn test_handler(_: Request, _: Response, _: Captures) {}
    let mut router = Router::new();
    router.add_route(Method::Get, r"/[", test_handler);
    let e = router.finalize();
    assert_eq!(e.err(), Some(RouterError::BadSet));
}
<|endoftext|>


<commit_before>//! Data storage schemes.

#[cfg(test)]
extern crate assert;

extern crate num;

mod matrix;

pub use matrix::band::Matrix as BandMatix;
pub use matrix::compressed::Matrix as CompressedMatix;
pub use matrix::compressed::Format as CompressedFormat;
pub use matrix::diagonal::Matrix as DiagonalMatrix;
pub use matrix::packed::Matrix as PackedMatrix;
pub use matrix::packed::Format as PackedFormat;
<commit_msg>Fix a typo<commit_after>//! Data storage schemes.

#[cfg(test)]
extern crate assert;

extern crate num;

mod matrix;

pub use matrix::band::Matrix as BandMatrix;
pub use matrix::compressed::Matrix as CompressedMatrix;
pub use matrix::compressed::Format as CompressedFormat;
pub use matrix::diagonal::Matrix as DiagonalMatrix;
pub use matrix::packed::Matrix as PackedMatrix;
pub use matrix::packed::Format as PackedFormat;
<|endoftext|>