<commit_before>extern crate clap;
extern crate iron;
extern crate pretty_bytes;
extern crate chrono;
extern crate ansi_term;

use std::env;
use std::fs::{self, File};
use std::path::{PathBuf};
use std::error::Error;
use std::time::{SystemTime, UNIX_EPOCH};
use std::os::unix::ffi::OsStrExt;

use iron::headers;
use iron::status;
use iron::mime;
use iron::{Iron, Request, Response, IronResult, Set, Chain, Handler, AfterMiddleware};
use pretty_bytes::converter::convert;
use chrono::{DateTime, Local, TimeZone};
use ansi_term::Colour::{Red, Green, Yellow, Blue};

fn main() {
    let matches = clap::App::new("Simple HTTP Server")
        .arg(clap::Arg::with_name("root")
             .index(1)
             .validator(|s| {
                 match File::open(s) {
                     Ok(f) => {
                         if f.metadata().unwrap().is_dir() { Ok(()) } else {
                             Err("Not directory".to_owned())
                         }
                     },
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("Root directory"))
        .arg(clap::Arg::with_name("index")
             .short("i")
             .long("index")
             .help("Automatic render index page [index.html, index.htm]"))
        .arg(clap::Arg::with_name("port")
             .short("p")
             .long("port")
             .takes_value(true)
             .default_value("8000")
             .validator(|s| {
                 match s.parse::<u16>() {
                     Ok(_) => Ok(()),
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("Port number"))
        .arg(clap::Arg::with_name("threads")
             .short("t")
             .long("threads")
             .takes_value(true)
             .default_value("3")
             .validator(|s| {
                 match s.parse::<u8>() {
                     Ok(v) => {
                         if v > 0 { Ok(()) } else {
                             Err("Nagetive threads".to_owned())
                         }
                     }
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("How many http threads"))
        .get_matches();
    let root = matches
        .value_of("root")
        .map(|s| PathBuf::from(s))
        .unwrap_or(env::current_dir().unwrap());
    let index = matches.is_present("index");
    let port = matches
        .value_of("port")
        .unwrap()
        .parse::<u16>()
        .unwrap();
    let threads = matches
        .value_of("threads")
        .unwrap()
        .parse::<u8>()
        .unwrap();

    let addr = format!("0.0.0.0:{}", port);
    println!("   Root: {}", Blue.paint(root.to_str().unwrap()));
    println!("  Index: {}", Blue.paint(index.to_string()));
    println!("Address: {}", Blue.paint(format!("http://{}", addr)));
    println!("======== [{}] ========", Blue.paint(now_string()));

    let mut chain = Chain::new(MainHandler{root: root, index: index});
    chain.link_after(RequestLogger);
    let mut server = Iron::new(chain);
    server.threads = threads as usize;
    server.http(addr).unwrap();
}

struct MainHandler { root: PathBuf, index: bool }
struct RequestLogger;

impl MainHandler {
    fn send_file(&self, mut resp: Response, path: &PathBuf) -> IronResult<Response> {
        resp.set_mut(path.as_path());
        if resp.headers.get::<headers::ContentType>() == Some(
            &headers::ContentType(mime::Mime(mime::TopLevel::Text, mime::SubLevel::Plain, vec![]))
        ) {
            resp.headers.set(headers::ContentDisposition {
                disposition: headers::DispositionType::Attachment,
                parameters: vec![headers::DispositionParam::Filename(
                    headers::Charset::Ext("utf-8".to_owned()), // The character set for the bytes of the filename
                    None, // The optional language tag (see `language-tag` crate)
                    path.file_name().unwrap().as_bytes().to_vec() // the actual bytes of the filename
                )]
            });
            let default_mime: iron::mime::Mime = "application/octet-stream".parse().unwrap();
            resp.headers.set(headers::ContentType(default_mime));
        }
        return Ok(resp)
    }
}

impl Handler for MainHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let mut path = self.root.clone();
        for part in req.url.path() {
            path.push(part);
        }
        let root_link: &'static str = "[ROOT]";

        match File::open(&path) {
            Ok(f) => {
                let mut resp = Response::with(status::Ok);
                let metadata = f.metadata().unwrap();
                if metadata.is_dir() {
                    let mut rows = Vec::new();

                    let path_prefix = req.url.path()
                        .into_iter()
                        .filter(|s| !s.is_empty())
                        .collect::<Vec<&str>>();
                    let breadcrumb = if path_prefix.len() > 0 {
                        let mut breadcrumb = path_prefix.clone();
                        let mut bread_links: Vec<String> = Vec::new();
                        bread_links.push(breadcrumb.pop().unwrap().to_owned());
                        while breadcrumb.len() > 0 {
                            let link = breadcrumb.join("/");
                            bread_links.push(format!(
                                "{}",
                                link, breadcrumb.pop().unwrap().to_owned(),
                            ));
                        }
                        bread_links.push(root_link.to_owned());
                        bread_links.reverse();
                        bread_links.join(" / ")
                    } else { root_link.to_owned() };

                    if path_prefix.len() > 0 {
                        let mut link = path_prefix.clone();
                        link.pop();
                        rows.push(format!(
                            "
{}
",
                            link.join("/"), "[Parent Directory]"
                        ));
                    } else {
                        rows.push("

".to_owned());
                    }
                    for entry in fs::read_dir(&path).unwrap() {
                        let entry = entry.unwrap();
                        let entry_meta = entry.metadata().unwrap();
                        let file_name = entry.file_name().into_string().unwrap();
                        if self.index {
                            for fname in vec!["index.html", "index.htm"] {
                                if file_name == fname {
                                    path.push(file_name);
                                    return self.send_file(resp, &path);
                                }
                            }
                        }
                        let file_modified = system_time_to_date_time(entry_meta.modified().unwrap())
                            .format("%Y-%m-%d %H:%M:%S").to_string();
                        let file_size = convert(entry_meta.len() as f64);
                        let file_type = entry_meta.file_type();
                        let link_style = if file_type.is_dir() {
                            "style=\"text-decoration: none; font-weight: bold;\"".to_owned()
                        } else {
                            "style=\"text-decoration: none;\"".to_owned()
                        };
                        let mut link = path_prefix.clone();
                        link.push(&file_name);
                        let link = link.join("/");
                        rows.push(format!(
                            "
{}	 [{}]	 <bold>{}</bold>
",
                            link_style, link, file_name, file_modified, file_size
                        ));
                    }
                    resp.headers.set(headers::ContentType::html());
                    resp.set_mut(format!(
                        "{}

{}
",
                        breadcrumb, rows.join("\n")
                    ));
                    Ok(resp)
                } else {
                    self.send_file(resp, &path)
                }
            },
            Err(e) => {
                let mut resp = Response::with((status::NotFound, format!(
                    "{}

[ERROR]: {}
",
                    root_link, e.description().to_string()
                )));
                resp.headers.set(headers::ContentType::html());
                Ok(resp)
            }
        }
    }
}

impl AfterMiddleware for RequestLogger {
    fn after(&self, req: &mut Request, resp: Response) -> IronResult<Response> {
        let status = resp.status.unwrap();
        let status_str = if status.is_success() {
            Green.bold().paint(status.to_u16().to_string())
        } else if status.is_informational() {
            Yellow.bold().paint(status.to_u16().to_string())
        } else {
            Red.bold().paint(status.to_u16().to_string())
        };

        println!(
            // datetime, remote-ip, status-code, method, url-path
            "[{}] - {} - {} - {} /{}",
            now_string(),
            req.remote_addr.ip(),
            status_str,
            req.method,
            req.url.as_ref().to_string().splitn(4, '/').collect::<Vec<&str>>().pop().unwrap()
        );
        Ok(resp)
    }
}

fn now_string() -> String {
    Local::now().format("%Y-%m-%d %H:%M:%S").to_string()
}

fn system_time_to_date_time(t: SystemTime) -> DateTime<Local> {
    let (sec, nsec) = match t.duration_since(UNIX_EPOCH) {
        Ok(dur) => (dur.as_secs() as i64, dur.subsec_nanos()),
        Err(e) => { // unlikely but should be handled
            let dur = e.duration();
            let (sec, nsec) = (dur.as_secs() as i64, dur.subsec_nanos());
            if nsec == 0 {
                (-sec, 0)
            } else {
                (-sec - 1, 1_000_000_000 - nsec)
            }
        },
    };
    Local.timestamp(sec, nsec)
}
<commit_msg>Change datetime font color<commit_after>extern crate clap;
extern crate iron;
extern crate pretty_bytes;
extern crate chrono;
extern crate ansi_term;

use std::env;
use std::fs::{self, File};
use std::path::{PathBuf};
use std::error::Error;
use std::time::{SystemTime, UNIX_EPOCH};
use std::os::unix::ffi::OsStrExt;

use iron::headers;
use iron::status;
use iron::mime;
use iron::{Iron, Request, Response, IronResult, Set, Chain, Handler, AfterMiddleware};
use pretty_bytes::converter::convert;
use chrono::{DateTime, Local, TimeZone};
use ansi_term::Colour::{Red, Green, Yellow, Blue};

fn main() {
    let matches = clap::App::new("Simple HTTP Server")
        .arg(clap::Arg::with_name("root")
             .index(1)
             .validator(|s| {
                 match File::open(s) {
                     Ok(f) => {
                         if f.metadata().unwrap().is_dir() { Ok(()) } else {
                             Err("Not directory".to_owned())
                         }
                     },
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("Root directory"))
        .arg(clap::Arg::with_name("index")
             .short("i")
             .long("index")
             .help("Automatic render index page [index.html, index.htm]"))
        .arg(clap::Arg::with_name("port")
             .short("p")
             .long("port")
             .takes_value(true)
             .default_value("8000")
             .validator(|s| {
                 match s.parse::<u16>() {
                     Ok(_) => Ok(()),
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("Port number"))
        .arg(clap::Arg::with_name("threads")
             .short("t")
             .long("threads")
             .takes_value(true)
             .default_value("3")
             .validator(|s| {
                 match s.parse::<u8>() {
                     Ok(v) => {
                         if v > 0 { Ok(()) } else {
                             Err("Nagetive threads".to_owned())
                         }
                     }
                     Err(e) => Err(e.description().to_string())
                 }
             })
             .help("How many http threads"))
        .get_matches();
    let root = matches
        .value_of("root")
        .map(|s| PathBuf::from(s))
        .unwrap_or(env::current_dir().unwrap());
    let index = matches.is_present("index");
    let port = matches
        .value_of("port")
        .unwrap()
        .parse::<u16>()
        .unwrap();
    let threads = matches
        .value_of("threads")
        .unwrap()
        .parse::<u8>()
        .unwrap();

    let addr = format!("0.0.0.0:{}", port);
    println!("   Root: {}", Blue.paint(root.to_str().unwrap()));
    println!("  Index: {}", Blue.paint(index.to_string()));
    println!("Address: {}", Blue.paint(format!("http://{}", addr)));
    println!("======== [{}] ========", Blue.paint(now_string()));

    let mut chain = Chain::new(MainHandler{root: root, index: index});
    chain.link_after(RequestLogger);
    let mut server = Iron::new(chain);
    server.threads = threads as usize;
    server.http(addr).unwrap();
}

struct MainHandler { root: PathBuf, index: bool }
struct RequestLogger;

impl MainHandler {
    fn send_file(&self, mut resp: Response, path: &PathBuf) -> IronResult<Response> {
        resp.set_mut(path.as_path());
        if resp.headers.get::<headers::ContentType>() == Some(
            &headers::ContentType(mime::Mime(mime::TopLevel::Text, mime::SubLevel::Plain, vec![]))
        ) {
            resp.headers.set(headers::ContentDisposition {
                disposition: headers::DispositionType::Attachment,
                parameters: vec![headers::DispositionParam::Filename(
                    headers::Charset::Ext("utf-8".to_owned()), // The character set for the bytes of the filename
                    None, // The optional language tag (see `language-tag` crate)
                    path.file_name().unwrap().as_bytes().to_vec() // the actual bytes of the filename
                )]
            });
            let default_mime: iron::mime::Mime = "application/octet-stream".parse().unwrap();
            resp.headers.set(headers::ContentType(default_mime));
        }
        return Ok(resp)
    }
}

impl Handler for MainHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let mut path = self.root.clone();
        for part in req.url.path() {
            path.push(part);
        }
        let root_link: &'static str = "[ROOT]";

        match File::open(&path) {
            Ok(f) => {
                let mut resp = Response::with(status::Ok);
                let metadata = f.metadata().unwrap();
                if metadata.is_dir() {
                    let mut rows = Vec::new();

                    let path_prefix = req.url.path()
                        .into_iter()
                        .filter(|s| !s.is_empty())
                        .collect::<Vec<&str>>();
                    let breadcrumb = if path_prefix.len() > 0 {
                        let mut breadcrumb = path_prefix.clone();
                        let mut bread_links: Vec<String> = Vec::new();
                        bread_links.push(breadcrumb.pop().unwrap().to_owned());
                        while breadcrumb.len() > 0 {
                            let link = breadcrumb.join("/");
                            bread_links.push(format!(
                                "{}",
                                link, breadcrumb.pop().unwrap().to_owned(),
                            ));
                        }
                        bread_links.push(root_link.to_owned());
                        bread_links.reverse();
                        bread_links.join(" / ")
                    } else { root_link.to_owned() };

                    if path_prefix.len() > 0 {
                        let mut link = path_prefix.clone();
                        link.pop();
                        rows.push(format!(
                            "
{}
",
                            link.join("/"), "[Parent Directory]"
                        ));
                    } else {
                        rows.push("

".to_owned());
                    }
                    for entry in fs::read_dir(&path).unwrap() {
                        let entry = entry.unwrap();
                        let entry_meta = entry.metadata().unwrap();
                        let file_name = entry.file_name().into_string().unwrap();
                        if self.index {
                            for fname in vec!["index.html", "index.htm"] {
                                if file_name == fname {
                                    path.push(file_name);
                                    return self.send_file(resp, &path);
                                }
                            }
                        }
                        let file_modified = system_time_to_date_time(entry_meta.modified().unwrap())
                            .format("%Y-%m-%d %H:%M:%S").to_string();
                        let file_size = convert(entry_meta.len() as f64);
                        let file_type = entry_meta.file_type();
                        let link_style = if file_type.is_dir() {
                            "style=\"text-decoration: none; font-weight: bold;\"".to_owned()
                        } else {
                            "style=\"text-decoration: none;\"".to_owned()
                        };
                        let mut link = path_prefix.clone();
                        link.push(&file_name);
                        let link = link.join("/");
                        rows.push(format!(
                            "
{}	 [{}]	 <bold>{}</bold>
",
                            link_style, link, file_name, file_modified, file_size
                        ));
                    }
                    resp.headers.set(headers::ContentType::html());
                    resp.set_mut(format!(
                        "{}

{}
",
                        breadcrumb, rows.join("\n")
                    ));
                    Ok(resp)
                } else {
                    self.send_file(resp, &path)
                }
            },
            Err(e) => {
                let mut resp = Response::with((status::NotFound, format!(
                    "{}

[ERROR]: {}
",
                    root_link, e.description().to_string()
                )));
                resp.headers.set(headers::ContentType::html());
                Ok(resp)
            }
        }
    }
}

impl AfterMiddleware for RequestLogger {
    fn after(&self, req: &mut Request, resp: Response) -> IronResult<Response> {
        let status = resp.status.unwrap();
        let status_str = if status.is_success() {
            Green.bold().paint(status.to_u16().to_string())
        } else if status.is_informational() {
            Yellow.bold().paint(status.to_u16().to_string())
        } else {
            Red.bold().paint(status.to_u16().to_string())
        };

        println!(
            // datetime, remote-ip, status-code, method, url-path
            "[{}] - {} - {} - {} /{}",
            now_string(),
            req.remote_addr.ip(),
            status_str,
            req.method,
            req.url.as_ref().to_string().splitn(4, '/').collect::<Vec<&str>>().pop().unwrap()
        );
        Ok(resp)
    }
}

fn now_string() -> String {
    Local::now().format("%Y-%m-%d %H:%M:%S").to_string()
}

fn system_time_to_date_time(t: SystemTime) -> DateTime<Local> {
    let (sec, nsec) = match t.duration_since(UNIX_EPOCH) {
        Ok(dur) => (dur.as_secs() as i64, dur.subsec_nanos()),
        Err(e) => { // unlikely but should be handled
            let dur = e.duration();
            let (sec, nsec) = (dur.as_secs() as i64, dur.subsec_nanos());
            if nsec == 0 {
                (-sec, 0)
            } else {
                (-sec - 1, 1_000_000_000 - nsec)
            }
        },
    };
    Local.timestamp(sec, nsec)
}
<|endoftext|>


<commit_before>extern crate time;

use std::collections::LinkedList;
use std::str::Split;

fn main() {
    let dow = ["Duinday", "Sitaday", "Wikiday", "Tuxday", "Gnuday", "Commonday"];
    let moy = ["Jabim", "Zodrak", "Trogool", "Yanar", "Shkumbe", "Habniah", "Skarl", "Mikon", "Pertunda", "Kib", "Broket"];
    let dpm = 33;
    let dpw = dow.len();
    let mpy = moy.len();
    let (year, month, day, yoff) = current_day(time::now());
    let wd = (yoff + month * 3 + day) % dpw;
    let mut moff = yoff;
    let mut months_across = LinkedList::<String>::new();

    for mm in 0..mpy {
        let spaces = (17 - moy[mm].len()) / 2;
        let mut month_text = format!("");
        for _ in 0..spaces {
            month_text = format!("{} ", month_text);
        }

        month_text = format!("{}{}\n", month_text, moy[mm]);
        for dd in 0..dpw {
            let mut abbrd = String::from(dow[dd]);
            abbrd.truncate(2);
            month_text = format!("{}{} ", month_text, abbrd);
        }

        let dd = if mm == month { day } else { 1000 };
        let days = format_days(moff, dpm, dpw, dd);
        month_text = format!("{}{}", month_text, days.0);
        moff = days.1;
        if mm == 2 {
            month_text = format!("{}--  Peer  Day  --", month_text);
        }
        else if mm == 6 {
            month_text = format!("{}--Torrent Feast--", month_text);
        }
        else if is_leap_year(year) && mm == 10 {
            month_text = format!("{}--Immersion Day--", month_text);
        }

        month_text = format!("{}\n", month_text);
        print!("{}", month_text);
        months_across.push_back(month_text);
    }

    let mut datestr = format!("{}, {:02} of {}", dow[wd], day, moy[month]);
    let mut daystr = format!("{:02}.{:02}", month + 1, day);
    if day == 34 {
        if month == 2 {
            datestr = format!("Peer Day");
            daystr = format!("P");
        }
        else if month == 6 {
            datestr = format!("Torrent Feast");
            daystr = format!("T");
        }
        else if month == 10 {
            datestr = format!("Immersion Feast");
            daystr = format!("T");
        }
    }
    let hol = format!("{}", what_holiday(month, day));
    println!("Today is {} {}{}.  [{}.{}]", datestr, year, hol, year, daystr);
}

fn format_days(moff: usize, dpm: usize, dpw: usize, highlight: usize) -> (String, usize) {
    let mut month = format!("");

    if moff != 0 {
        month = format!("{}\n", month);
    }

    for _ in 0 .. moff {
        month = format!("{}   ", month);
    }

    for day in 1 .. dpm + 1 {
        if (day + moff) % dpw == 1 {
            month = format!("{}\n", month);
        }

        let ch = if day == highlight { ">" } else if day + 1 == highlight { "<" } else { " " };
        month = format!("{}{:2}{}", month, day, ch);
    }

    month = format!("{}\n", month);
    return (month, if moff == 0 { 3 } else { 0 });
}

fn current_day(current_time: time::Tm) -> (usize, usize, usize, usize) {
    let epoch_days_offset = 1483889;
    let seconds_per_day = 86400;
    let now = current_time.to_timespec();
    let days_since_epoch = (epoch_days_offset + now.sec / seconds_per_day) as i32;
    let days_per_year = 365;
    let leap_year = 4;
    let not_leap_year = 33;
    let days_per_month = 33;

    let mut count = 1;
    let mut days_remaining = days_since_epoch;
    let mut year = 0;
    while days_remaining > days_per_year + 1 {
        days_remaining -= days_per_year;
        year += 1;
        if count > not_leap_year {
            count = 1;
        }
        if count % leap_year == 0 {
            days_remaining -= 1;
        }
        count += 1;
    }
    if days_remaining == days_per_year + 1 && count % leap_year == 0 {
        days_remaining = 0;
        year += 1;
    }

    let mut month = 0;
    while days_remaining > days_per_month {
        month += 1;
        days_remaining -= days_per_month;
        if month == 3 || month == 7 || month == 11 {
            days_remaining -= 1;
        }
    }

    let day = days_remaining;
    return (year, month as usize, day as usize + 1, (year % 2 * 3) as usize);
}

fn is_leap_year(year: usize) -> bool {
    let rem = year % 33;
    return rem != 0 && rem % 4 == 0;
}

fn what_holiday(month: usize, day: usize) -> String {
    let mut result = format!("");
    if month == 0 && day == 1 {
        result = format!(", New Year's Day");
    }
    else if month == 2 && day == 12 {
        result = format!(", Purification Day");
    }
    else if month == 2 && day == 24 {
        result = format!(", Document Freedom Day");
    }
    else if month == 3 && day == 33 {
        result = format!(", Hardware Freedom Day");
    }
    else if month == 5 && day == 4 {
        result = format!(", Harvest Gift");
    }
    else if month == 5 && day == 9 {
        result = format!(", Culture Freedom Day");
    }
    else if month == 7 && day == 29 {
        result = format!(", Familytide");
    }
    else if month == 8 && day == 33 {
        result = format!(", Software Freedom Day");
    }
    else if month == 9 && day == 30 {
        result = format!(", Open Access Day");
    }
    else if month == 10 && day == 21 {
        result = format!(", Freedom Day");
    }
    else if month == 0 && day == 27 {
        result = format!(", International Workers' Day");
    }
    return result;
}

fn month_zipper(months: LinkedList<String>, buffer: &str, front: usize) {
    let month_iterator = months.iter();
    let mut length = 0;
    let mut split_months = LinkedList::<Split<&str>>::new();
    for m in month_iterator {
        let split = m.split("\n");
        if split.clone().count() > length {
            length = split.clone().count();
        }
        split_months.push_back(split);
    }

    for i in 0..(length - 1) {
        for _ in 0..front {
            print!(" ");
        }

        let split_iterator = split_months.iter();
        for m in split_iterator {
            let line = m.clone().nth(i);
            match line {
                Some(l) => print!("{}{}", if l == "" { "                  " } else { l }, buffer),
                None => {},
            }
        }

        println!("");
    }
}

<commit_msg>Fix day-of-week calculation<commit_after>extern crate time;

use std::collections::LinkedList;
use std::str::Split;

fn main() {
    let dow = ["Duinday", "Sitaday", "Wikiday", "Tuxday", "Gnuday", "Commonday"];
    let moy = ["Jabim", "Zodrak", "Trogool", "Yanar", "Shkumbe", "Habniah", "Skarl", "Mikon", "Pertunda", "Kib", "Broket"];
    let dpm = 33;
    let dpw = dow.len();
    let mpy = moy.len();
    let (year, month, day, yoff) = current_day(time::now());
    let wd = (yoff + month * 3 + day - 1) % dpw;
    let mut moff = yoff;
    let mut months_across = LinkedList::<String>::new();

    for mm in 0..mpy {
        let spaces = (17 - moy[mm].len()) / 2;
        let mut month_text = format!("");
        for _ in 0..spaces {
            month_text = format!("{} ", month_text);
        }

        month_text = format!("{}{}\n", month_text, moy[mm]);
        for dd in 0..dpw {
            let mut abbrd = String::from(dow[dd]);
            abbrd.truncate(2);
            month_text = format!("{}{} ", month_text, abbrd);
        }

        let dd = if mm == month { day } else { 1000 };
        let days = format_days(moff, dpm, dpw, dd);
        month_text = format!("{}{}", month_text, days.0);
        moff = days.1;
        if mm == 2 {
            month_text = format!("{}--  Peer  Day  --", month_text);
        }
        else if mm == 6 {
            month_text = format!("{}--Torrent Feast--", month_text);
        }
        else if is_leap_year(year) && mm == 10 {
            month_text = format!("{}--Immersion Day--", month_text);
        }

        month_text = format!("{}\n", month_text);
        print!("{}", month_text);
        months_across.push_back(month_text);
    }

    let mut datestr = format!("{}, {:02} of {}", dow[wd], day, moy[month]);
    let mut daystr = format!("{:02}.{:02}", month + 1, day);
    if day == 34 {
        if month == 2 {
            datestr = format!("Peer Day");
            daystr = format!("P");
        }
        else if month == 6 {
            datestr = format!("Torrent Feast");
            daystr = format!("T");
        }
        else if month == 10 {
            datestr = format!("Immersion Feast");
            daystr = format!("T");
        }
    }
    let hol = format!("{}", what_holiday(month, day));
    println!("Today is {} {}{}.  [{}.{}]", datestr, year, hol, year, daystr);
}

fn format_days(moff: usize, dpm: usize, dpw: usize, highlight: usize) -> (String, usize) {
    let mut month = format!("");

    if moff != 0 {
        month = format!("{}\n", month);
    }

    for _ in 0 .. moff {
        month = format!("{}   ", month);
    }

    for day in 1 .. dpm + 1 {
        if (day + moff) % dpw == 1 {
            month = format!("{}\n", month);
        }

        let ch = if day == highlight { ">" } else if day + 1 == highlight { "<" } else { " " };
        month = format!("{}{:2}{}", month, day, ch);
    }

    month = format!("{}\n", month);
    return (month, if moff == 0 { 3 } else { 0 });
}

fn current_day(current_time: time::Tm) -> (usize, usize, usize, usize) {
    let epoch_days_offset = 1483889;
    let seconds_per_day = 86400;
    let now = current_time.to_timespec();
    let days_since_epoch = (epoch_days_offset + now.sec / seconds_per_day) as i32;
    let days_per_year = 365;
    let leap_year = 4;
    let not_leap_year = 33;
    let days_per_month = 33;

    let mut count = 1;
    let mut days_remaining = days_since_epoch;
    let mut year = 0;
    while days_remaining > days_per_year + 1 {
        days_remaining -= days_per_year;
        year += 1;
        if count > not_leap_year {
            count = 1;
        }
        if count % leap_year == 0 {
            days_remaining -= 1;
        }
        count += 1;
    }
    if days_remaining == days_per_year + 1 && count % leap_year == 0 {
        days_remaining = 0;
        year += 1;
    }

    let mut month = 0;
    while days_remaining > days_per_month {
        month += 1;
        days_remaining -= days_per_month;
        if month == 3 || month == 7 || month == 11 {
            days_remaining -= 1;
        }
    }

    let day = days_remaining;
    return (year, month as usize, day as usize + 1, (year % 2 * 3) as usize);
}

fn is_leap_year(year: usize) -> bool {
    let rem = year % 33;
    return rem != 0 && rem % 4 == 0;
}

fn what_holiday(month: usize, day: usize) -> String {
    let mut result = format!("");
    if month == 0 && day == 1 {
        result = format!(", New Year's Day");
    }
    else if month == 2 && day == 12 {
        result = format!(", Purification Day");
    }
    else if month == 2 && day == 24 {
        result = format!(", Document Freedom Day");
    }
    else if month == 3 && day == 33 {
        result = format!(", Hardware Freedom Day");
    }
    else if month == 5 && day == 4 {
        result = format!(", Harvest Gift");
    }
    else if month == 5 && day == 9 {
        result = format!(", Culture Freedom Day");
    }
    else if month == 7 && day == 29 {
        result = format!(", Familytide");
    }
    else if month == 8 && day == 33 {
        result = format!(", Software Freedom Day");
    }
    else if month == 9 && day == 30 {
        result = format!(", Open Access Day");
    }
    else if month == 10 && day == 21 {
        result = format!(", Freedom Day");
    }
    else if month == 0 && day == 27 {
        result = format!(", International Workers' Day");
    }
    return result;
}

fn month_zipper(months: LinkedList<String>, buffer: &str, front: usize) {
    let month_iterator = months.iter();
    let mut length = 0;
    let mut split_months = LinkedList::<Split<&str>>::new();
    for m in month_iterator {
        let split = m.split("\n");
        if split.clone().count() > length {
            length = split.clone().count();
        }
        split_months.push_back(split);
    }

    for i in 0..(length - 1) {
        for _ in 0..front {
            print!(" ");
        }

        let split_iterator = split_months.iter();
        for m in split_iterator {
            let line = m.clone().nth(i);
            match line {
                Some(l) => print!("{}{}", if l == "" { "                  " } else { l }, buffer),
                None => {},
            }
        }

        println!("");
    }
}

<|endoftext|>


<commit_before>//! Utilities for generating random values
//!
//! The entire [`rand`](https://github.com/rust-lang-nursery/rand) crate which allows you to
//! generate random values is re-exported for your convenience. That means that you can use any
//! of its parts by importing from this module.
//! See the documentation for [`rand_crate`](../../rand/index.html).
//!
//! ```rust,no_run
//! extern crate turtle;
//! use turtle::rand::Rand;
//! # fn main() {}
//! ```
//!
//! The [`random()`] function is the most common function you will use. In fact,
//! it's exported from the turtle crate directly so you don't even have to use the `rand` module
//! in order to access it.
//!
//! Instead of this:
//!
//! ```rust,no_run
//! extern crate turtle;
//! use turtle::Turtle;
//! use turtle::rand::random;
//! # fn main() {}
//! ```
//!
//! You can do this:
//!
//! ```rust,no_run
//! extern crate turtle;
//! use turtle::{Turtle, random};
//! # fn main() {}
//! ```
//!
//! This means that for the most part, unless you are doing something very advanced, you won't need
//! to import this module. The [`random()`] function should be enough for
//! most cases. See the next section for more information on that.
//!
//! # Generating Random Values
//!
//! The [`random()`] function allows you to generate random values for many different types.
//! The following are some examples of types that can be used with [`random()`]:
//!
//! * [`Distance`] - `f64` values greater than or equal to `0.0` and less than `1.0`
//! * [`Angle`] - `f64` values greater than or equal to `0.0` and less than `1.0`
//! * [`Speed`] - any of the speed values including instant
//! * [`Color`] - colors with random red, green, blue and alpha values (use
//!   [`opaque()`](../color/struct.Color.html#method.opaque) to get a solid random color)
//! * [`Point`] - a random point with two `f64` values greater than or equal to `0.0` and less than `1.0`
//! * and more!
//!
//! Using [`random()`] often requires you to specify a type that you want to generate. For example,
//! if you run the following, the compiler will tell you that it needs you to give it more
//! information about the type that you want to generate:
//!
//! ```rust,ignore,compile_fail,E0283,rust
//! # // Remove `ignore` when Rust 1.22 comes out and compile_fail is added
//! # extern crate turtle;
//! # use turtle::{Turtle, random};
//! # fn main() {
//! let mut turtle = Turtle::new();
//! turtle.set_speed(random());
//! # }
//! ```
//!
//! This will produce an error that looks something like the following:
//!
//! ```text
//! error[E0283]: type annotations required: cannot resolve `_: std::convert::Into<turtle::Speed>`
//!  --> src/rand.rs:5:8
//!   |
//! 5 | turtle.set_speed(random());
//!   |        ^^^^^^^^^
//! ```
//!
//! To resolve this, you can either annotate the type by generating the random value in a separate
//! variable, or use Rust's "turbofish" syntax.
//!
//! ```rust
//! # extern crate turtle;
//! # use turtle::{Turtle, Speed, random};
//! # fn main() {
//! let mut turtle = Turtle::new();
//! // 1. Separate out into a variable, then annotate the desired type
//! let speed: Speed = random();
//! turtle.set_speed(speed);
//! // 2. Turbofish syntax ::<T>
//! turtle.set_speed(random::<Speed>());
//! # }
//! ```
//!
//! # More Functions for Generating Random Values
//!
//! The [`random_range()`] function allows you to generate values in a given range. You provide
//! a lower bound and an upper bound. The number generated will be greater than or equal to the
//! lower bound and strictly less than the upper bound.
//!
//! ```rust
//! # extern crate turtle;
//! # use turtle::random_range;
//! # fn main() {
//! // Generates an f64 value between 394.0 and 499.99999...
//! let value: f64 = random_range(394.0, 500.0);
//! assert!(value >= 394.0 && value < 500.0);
//! // Generates a u64 value between 32 and 64
//! let value = random_range::<u64>(32, 65);
//! assert!(value >= 32 && value <= 64);
//! // You do not need to specify the type if the compiler has enough information:
//! fn foo(a: u64) {}
//! foo(random_range(381, 920));
//! # }
//! ```
//!
//! ## How can one function generate so many different return types?
//!
//! Knowing how [`random()`] works is **not required** in order to be able to use it. That being said,
//! it is an excellent example of combing the concepts of "generics" and "traits". If you are not
//! familiar with those concepts yet, take a look at the
//! [Rust book](https://doc.rust-lang.org/book/second-edition/). It has an excellent
//! [section on both generics and traits](https://doc.rust-lang.org/book/second-edition/ch10-00-generics.html).
//!
//! The type signature of the [`random()`] function is similar to the following:
//!
//! ```rust,ignore,compile_fail,E0308
//! # // Remove `ignore` when Rust 1.22 comes out and compile_fail is added
//! # extern crate turtle;
//! # use turtle::rand::Rand;
//! fn random<T: Rand>() -> T { /* ... */ }
//! # fn main() {}
//! ```
//!
//! This tells us the following:
//!
//! * The `random()` function takes **no arguments** and returns a value of type `T`
//! * The generic type `T` is required to implement the [`Rand`] trait
//!
//! This is the incredible part about this function. It requires *zero* arguments, and yet can
//! generate all kinds of values. This is because while it doesn't require any *parameters*, it
//! does take a single *type argument* in order to determine what type to generate a value of.
//! This is done at compile time so no work needs to be performed at runtime in order to determine
//! the type to generate or how to generate it.
//!
//! This also explains why we sometimes need to use the turbofish syntax (`::<T>`) in order to
//! specify the type `T`. When a function requires a type argument and doesn't take that argument
//! as one of its parameters, the compiler can often end up in a situation where it doesn't have
//! the necessary information to determine which type to return.
//! The turbofish syntax and type annotations provide two different ways to clarify what we want.
//!
//! That being said, there are a lot of situations where the compiler *can* figure out what type
//! we need. Each of the types we covered above, implements the [`Rand`] trait. We specified which
//! type we would like the function to return by annotating the variable that we assigned the
//! random value to.
//!
//! ```rust
//! # extern crate turtle;
//! # use turtle::{Speed, random};
//! # fn main() {
//! let speed: Speed = random();
//! # }
//! ```
//!
//! If we were passing the value to a function that is known to take [`Speed`] as its type, the
//! compiler can use that information to determine the return type of [`random()`]. The following
//! example compiles without any additional annotations:
//!
//! ```rust
//! # extern crate turtle;
//! # use turtle::{Speed, random};
//! # fn main() {
//! fn foo(speed: Speed) {}
//! // No type annotations required!
//! foo(random());
//! # }
//! ```
//!
//! This generates a random speed using the implementation of [`Rand`] for the [`Speed`] type in this
//! crate.
//!
//! ### The Orphan Rule
//! Not all of the implementations of [`Rand`] for the types above are implemented in this
//! crate. There is a rule known as the [orphan rule](https://doc.rust-lang.org/book/second-edition/ch10-02-traits.html#implementing-a-trait-on-a-type)
//! which prevents anyone from implementing a trait on a type that they do not define. That is why
//! we implemented [`Rand`] for [`Speed`] and [`Color`], but not for type aliases like
//! [`Distance`]. [`Distance`] is a type alias for `f64`. `f64` is provided by the standard
//! library, so we cannot implement any traits for it. The implementations of [`Rand`] for types
//! like that come from the `rand` crate itself.
//!
//! [`Rand`]: ../../rand/trait.Rand.html
//! [`random()`]: ../fn.random.html
//! [`random_range()`]: fn.random_range.html
//! [`Distance`]: ../type.Distance.html
//! [`Angle`]: ../type.Angle.html
//! [`Speed`]: ../speed/enum.Speed.html
//! [`Color`]: ../color/struct.Color.html
//! [`Point`]: ../type.Point.html

pub use rand_crate::*;

use self::distributions::range::SampleRange;

/// Generates a random value in the given range.
///
/// The value `x` that is returned will be such that low ≤ x < high.
///
/// # Panics
/// Panics if low ≥ high
///
/// # Example:
/// ```rust
/// # extern crate turtle;
/// # use turtle::random_range;
/// # fn main() {
/// // Generates an f64 value between 100 and 199
/// let value: f64 = random_range(100.0, 200.0);
/// assert!(value >= 100.0 && value < 200.0);
/// // Generates a u64 value between 1000 and 3000000
/// let value = random_range::<u64>(1000, 3000001);
/// assert!(value >= 1000 && value < 3000001);
/// // You do not need to specify the type if the compiler has enough information:
/// fn foo(a: u64) {}
/// foo(random_range(432, 1938));
/// # }
/// ```
pub fn random_range<T: PartialOrd + SampleRange>(low: T, high: T) -> T {
    thread_rng().gen_range(low, high)
}
<commit_msg>Adding compile fail tests now that Rust 1.22 is out!<commit_after>//! Utilities for generating random values
//!
//! The entire [`rand`](https://github.com/rust-lang-nursery/rand) crate which allows you to
//! generate random values is re-exported for your convenience. That means that you can use any
//! of its parts by importing from this module.
//! See the documentation for [`rand_crate`](../../rand/index.html).
//!
//! ```rust,no_run
//! extern crate turtle;
//! use turtle::rand::Rand;
//! # fn main() {}
//! ```
//!
//! The [`random()`] function is the most common function you will use. In fact,
//! it's exported from the turtle crate directly so you don't even have to use the `rand` module
//! in order to access it.
//!
//! Instead of this:
//!
//! ```rust,no_run
//! extern crate turtle;
//! use turtle::Turtle;
//! use turtle::rand::random;
//! # fn main() {}
//! ```
//!
//! You can do this:
//!
//! ```rust,no_run
//! extern crate turtle;
//! use turtle::{Turtle, random};
//! # fn main() {}
//! ```
//!
//! This means that for the most part, unless you are doing something very advanced, you won't need
//! to import this module. The [`random()`] function should be enough for
//! most cases. See the next section for more information on that.
//!
//! # Generating Random Values
//!
//! The [`random()`] function allows you to generate random values for many different types.
//! The following are some examples of types that can be used with [`random()`]:
//!
//! * [`Distance`] - `f64` values greater than or equal to `0.0` and less than `1.0`
//! * [`Angle`] - `f64` values greater than or equal to `0.0` and less than `1.0`
//! * [`Speed`] - any of the speed values including instant
//! * [`Color`] - colors with random red, green, blue and alpha values (use
//!   [`opaque()`](../color/struct.Color.html#method.opaque) to get a solid random color)
//! * [`Point`] - a random point with two `f64` values greater than or equal to `0.0` and less than `1.0`
//! * and more!
//!
//! Using [`random()`] often requires you to specify a type that you want to generate. For example,
//! if you run the following, the compiler will tell you that it needs you to give it more
//! information about the type that you want to generate:
//!
//! ```rust,compile_fail,E0283
//! # extern crate turtle;
//! # use turtle::{Turtle, random};
//! # fn main() {
//! let mut turtle = Turtle::new();
//! turtle.set_speed(random());
//! # }
//! ```
//!
//! This will produce an error that looks something like the following:
//!
//! ```text
//! error[E0283]: type annotations required: cannot resolve `_: std::convert::Into<turtle::Speed>`
//!  --> src/rand.rs:5:8
//!   |
//! 5 | turtle.set_speed(random());
//!   |        ^^^^^^^^^
//! ```
//!
//! To resolve this, you can either annotate the type by generating the random value in a separate
//! variable, or use Rust's "turbofish" syntax.
//!
//! ```rust
//! # extern crate turtle;
//! # use turtle::{Turtle, Speed, random};
//! # fn main() {
//! let mut turtle = Turtle::new();
//! // 1. Separate out into a variable, then annotate the desired type
//! let speed: Speed = random();
//! turtle.set_speed(speed);
//! // 2. Turbofish syntax ::<T>
//! turtle.set_speed(random::<Speed>());
//! # }
//! ```
//!
//! # More Functions for Generating Random Values
//!
//! The [`random_range()`] function allows you to generate values in a given range. You provide
//! a lower bound and an upper bound. The number generated will be greater than or equal to the
//! lower bound and strictly less than the upper bound.
//!
//! ```rust
//! # extern crate turtle;
//! # use turtle::random_range;
//! # fn main() {
//! // Generates an f64 value between 394.0 and 499.99999...
//! let value: f64 = random_range(394.0, 500.0);
//! assert!(value >= 394.0 && value < 500.0);
//! // Generates a u64 value between 32 and 64
//! let value = random_range::<u64>(32, 65);
//! assert!(value >= 32 && value <= 64);
//! // You do not need to specify the type if the compiler has enough information:
//! fn foo(a: u64) {}
//! foo(random_range(381, 920));
//! # }
//! ```
//!
//! ## How can one function generate so many different return types?
//!
//! Knowing how [`random()`] works is **not required** in order to be able to use it. That being said,
//! it is an excellent example of combing the concepts of "generics" and "traits". If you are not
//! familiar with those concepts yet, take a look at the
//! [Rust book](https://doc.rust-lang.org/book/second-edition/). It has an excellent
//! [section on both generics and traits](https://doc.rust-lang.org/book/second-edition/ch10-00-generics.html).
//!
//! The type signature of the [`random()`] function is similar to the following:
//!
//! ```rust,compile_fail,E0308
//! # extern crate turtle;
//! # use turtle::rand::Rand;
//! fn random<T: Rand>() -> T { /* ... */ }
//! # fn main() {}
//! ```
//!
//! This tells us the following:
//!
//! * The `random()` function takes **no arguments** and returns a value of type `T`
//! * The generic type `T` is required to implement the [`Rand`] trait
//!
//! This is the incredible part about this function. It requires *zero* arguments, and yet can
//! generate all kinds of values. This is because while it doesn't require any *parameters*, it
//! does take a single *type argument* in order to determine what type to generate a value of.
//! This is done at compile time so no work needs to be performed at runtime in order to determine
//! the type to generate or how to generate it.
//!
//! This also explains why we sometimes need to use the turbofish syntax (`::<T>`) in order to
//! specify the type `T`. When a function requires a type argument and doesn't take that argument
//! as one of its parameters, the compiler can often end up in a situation where it doesn't have
//! the necessary information to determine which type to return.
//! The turbofish syntax and type annotations provide two different ways to clarify what we want.
//!
//! That being said, there are a lot of situations where the compiler *can* figure out what type
//! we need. Each of the types we covered above, implements the [`Rand`] trait. We specified which
//! type we would like the function to return by annotating the variable that we assigned the
//! random value to.
//!
//! ```rust
//! # extern crate turtle;
//! # use turtle::{Speed, random};
//! # fn main() {
//! let speed: Speed = random();
//! # }
//! ```
//!
//! If we were passing the value to a function that is known to take [`Speed`] as its type, the
//! compiler can use that information to determine the return type of [`random()`]. The following
//! example compiles without any additional annotations:
//!
//! ```rust
//! # extern crate turtle;
//! # use turtle::{Speed, random};
//! # fn main() {
//! fn foo(speed: Speed) {}
//! // No type annotations required!
//! foo(random());
//! # }
//! ```
//!
//! This generates a random speed using the implementation of [`Rand`] for the [`Speed`] type in this
//! crate.
//!
//! ### The Orphan Rule
//! Not all of the implementations of [`Rand`] for the types above are implemented in this
//! crate. There is a rule known as the [orphan rule](https://doc.rust-lang.org/book/second-edition/ch10-02-traits.html#implementing-a-trait-on-a-type)
//! which prevents anyone from implementing a trait on a type that they do not define. That is why
//! we implemented [`Rand`] for [`Speed`] and [`Color`], but not for type aliases like
//! [`Distance`]. [`Distance`] is a type alias for `f64`. `f64` is provided by the standard
//! library, so we cannot implement any traits for it. The implementations of [`Rand`] for types
//! like that come from the `rand` crate itself.
//!
//! [`Rand`]: ../../rand/trait.Rand.html
//! [`random()`]: ../fn.random.html
//! [`random_range()`]: fn.random_range.html
//! [`Distance`]: ../type.Distance.html
//! [`Angle`]: ../type.Angle.html
//! [`Speed`]: ../speed/enum.Speed.html
//! [`Color`]: ../color/struct.Color.html
//! [`Point`]: ../type.Point.html

pub use rand_crate::*;

use self::distributions::range::SampleRange;

/// Generates a random value in the given range.
///
/// The value `x` that is returned will be such that low ≤ x < high.
///
/// # Panics
/// Panics if low ≥ high
///
/// # Example:
/// ```rust
/// # extern crate turtle;
/// # use turtle::random_range;
/// # fn main() {
/// // Generates an f64 value between 100 and 199
/// let value: f64 = random_range(100.0, 200.0);
/// assert!(value >= 100.0 && value < 200.0);
/// // Generates a u64 value between 1000 and 3000000
/// let value = random_range::<u64>(1000, 3000001);
/// assert!(value >= 1000 && value < 3000001);
/// // You do not need to specify the type if the compiler has enough information:
/// fn foo(a: u64) {}
/// foo(random_range(432, 1938));
/// # }
/// ```
pub fn random_range<T: PartialOrd + SampleRange>(low: T, high: T) -> T {
    thread_rng().gen_range(low, high)
}
<|endoftext|>


<commit_before>/// The Toml Read extensions

use toml::Value;

use tokenizer::tokenize_with_seperator;
use error::*;

pub trait TomlValueReadExt<'doc> {

    /// Extension function for reading a value from the current toml::Value document
    /// using a custom seperator
    fn read_with_seperator(&'doc self, query: &str, sep: char) -> Result<Option<&'doc Value>>;

    /// Extension function for reading a value from the current toml::Value document mutably
    /// using a custom seperator
    fn read_mut_with_seperator(&'doc mut self, query: &str, sep: char) -> Result<Option<&'doc mut Value>>;

    /// Extension function for reading a value from the current toml::Value document
    fn read(&'doc self, query: &str) -> Result<Option<&'doc Value>> {
        self.read_with_seperator(query, '.')
    }

    /// Extension function for reading a value from the current toml::Value document mutably
    fn read_mut(&'doc mut self, query: &str) -> Result<Option<&'doc mut Value>> {
        self.read_mut_with_seperator(query, '.')
    }

}

impl<'doc> TomlValueReadExt<'doc> for Value {

    fn read_with_seperator(&'doc self, query: &str, sep: char) -> Result<Option<&'doc Value>> {
        use resolver::non_mut_resolver::resolve;

        tokenize_with_seperator(query, sep).and_then(move |tokens| resolve(self, &tokens, false))
    }

    fn read_mut_with_seperator(&'doc mut self, query: &str, sep: char) -> Result<Option<&'doc mut Value>> {
        use resolver::mut_resolver::resolve;

        tokenize_with_seperator(query, sep).and_then(move |tokens| resolve(self, &tokens, false))
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_read_empty() {
        let toml : Value = toml_from_str("").unwrap();

        let val  = toml.read_with_seperator(&String::from("a"), '.');

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table"), '.');

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Table(_)));
        match val {
            &Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_read_table_value() {
        let toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table.a"), '.');

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Integer(1)));
    }

    #[test]
    fn test_read_empty_table_value() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table.a"), '.');
        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table_index() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table.[0]"), '.');
        assert!(val.is_err());
        let err = val.unwrap_err();

        assert!(is_match!(err.kind(), &ErrorKind::NoIndexInTable(_)));
    }

    ///
    ///
    /// Querying without specifying the seperator
    ///
    ///

    #[test]
    fn test_read_empty_without_seperator() {
        let toml : Value = toml_from_str("").unwrap();

        let val  = toml.read(&String::from("a"));
        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read(&String::from("table"));

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Table(_)));
        match val {
            &Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_read_table_value_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let val  = toml.read(&String::from("table.a"));

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Integer(1)));
    }

    #[test]
    fn test_read_empty_table_value_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read(&String::from("table.a"));
        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table_index_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read(&String::from("table.[0]"));
        assert!(val.is_err());
        let err = val.unwrap_err();

        assert!(is_match!(err.kind(), &ErrorKind::NoIndexInTable(_)));
    }

}

<commit_msg>Add higher-level read functions<commit_after>/// The Toml Read extensions

use toml::Value;

use tokenizer::tokenize_with_seperator;
use error::*;

pub trait TomlValueReadExt<'doc> {

    /// Extension function for reading a value from the current toml::Value document
    /// using a custom seperator
    fn read_with_seperator(&'doc self, query: &str, sep: char) -> Result<Option<&'doc Value>>;

    /// Extension function for reading a value from the current toml::Value document mutably
    /// using a custom seperator
    fn read_mut_with_seperator(&'doc mut self, query: &str, sep: char) -> Result<Option<&'doc mut Value>>;

    /// Extension function for reading a value from the current toml::Value document
    fn read(&'doc self, query: &str) -> Result<Option<&'doc Value>> {
        self.read_with_seperator(query, '.')
    }

    /// Extension function for reading a value from the current toml::Value document mutably
    fn read_mut(&'doc mut self, query: &str) -> Result<Option<&'doc mut Value>> {
        self.read_mut_with_seperator(query, '.')
    }

}

impl<'doc> TomlValueReadExt<'doc> for Value {

    fn read_with_seperator(&'doc self, query: &str, sep: char) -> Result<Option<&'doc Value>> {
        use resolver::non_mut_resolver::resolve;

        tokenize_with_seperator(query, sep).and_then(move |tokens| resolve(self, &tokens, false))
    }

    fn read_mut_with_seperator(&'doc mut self, query: &str, sep: char) -> Result<Option<&'doc mut Value>> {
        use resolver::mut_resolver::resolve;

        tokenize_with_seperator(query, sep).and_then(move |tokens| resolve(self, &tokens, false))
    }

}

pub trait TomlValueReadTypeExt<'doc> {
    fn read_string(&'doc self, query: &str) -> Result<String>;
    fn read_int(&'doc self, query: &str) -> Result<i64>;
    fn read_float(&'doc self, query: &str) -> Result<f64>;
    fn read_bool(&'doc self, query: &str) -> Result<bool>;
}

macro_rules! make_type_getter {
    ($fnname:ident, $type:ty, $typename:expr, $matcher:pat => $impl:expr) => {
        fn $fnname(&'doc self, query: &str) -> Result<$type> {
            self.read_with_seperator(query, '.').and_then(|o| match o {
                $matcher => $impl,
                Some(o)  => Err(ErrorKind::TypeError($typename, type_to_name(o)).into()),
                None     => Err(ErrorKind::NotAvailable(String::from(query)).into()),
            })
        }
    };
}

impl<'doc, T> TomlValueReadTypeExt<'doc> for T
    where T: TomlValueReadExt<'doc>
{
    make_type_getter!(read_string, String, "String",
                      Some(&Value::String(ref obj)) => Ok(obj.clone()));

    make_type_getter!(read_int, i64, "Integer",
                      Some(&Value::Integer(obj)) => Ok(obj));

    make_type_getter!(read_float, f64, "Float",
                      Some(&Value::Float(obj)) => Ok(obj));

    make_type_getter!(read_bool, bool, "Boolean",
                      Some(&Value::Boolean(obj)) => Ok(obj));
}

fn type_to_name(obj: &Value) -> &'static str {
    match *obj {
        Value::String(_)   => "String",
        Value::Integer(_)  => "Integer",
        Value::Float(_)    => "Float",
        Value::Boolean(_)  => "Boolean",
        Value::Datetime(_) => "Datetime",
        Value::Array(_)    => "Array",
        Value::Table(_)    => "Table",
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_read_empty() {
        let toml : Value = toml_from_str("").unwrap();

        let val  = toml.read_with_seperator(&String::from("a"), '.');

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table"), '.');

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Table(_)));
        match val {
            &Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_read_table_value() {
        let toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table.a"), '.');

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Integer(1)));
    }

    #[test]
    fn test_read_empty_table_value() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table.a"), '.');
        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table_index() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read_with_seperator(&String::from("table.[0]"), '.');
        assert!(val.is_err());
        let err = val.unwrap_err();

        assert!(is_match!(err.kind(), &ErrorKind::NoIndexInTable(_)));
    }

    ///
    ///
    /// Querying without specifying the seperator
    ///
    ///

    #[test]
    fn test_read_empty_without_seperator() {
        let toml : Value = toml_from_str("").unwrap();

        let val  = toml.read(&String::from("a"));
        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read(&String::from("table"));

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Table(_)));
        match val {
            &Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_read_table_value_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let val  = toml.read(&String::from("table.a"));

        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_some());
        let val = val.unwrap();

        assert!(is_match!(val, &Value::Integer(1)));
    }

    #[test]
    fn test_read_empty_table_value_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read(&String::from("table.a"));
        assert!(val.is_ok());
        let val = val.unwrap();

        assert!(val.is_none());
    }

    #[test]
    fn test_read_table_index_without_seperator() {
        let toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let val  = toml.read(&String::from("table.[0]"));
        assert!(val.is_err());
        let err = val.unwrap_err();

        assert!(is_match!(err.kind(), &ErrorKind::NoIndexInTable(_)));
    }

}

#[cfg(test)]
mod high_level_fn_test {
    use super::*;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_read_table_value() {
        let toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let val  = toml.read_int(&String::from("table.a"));

        assert!(val.is_ok());
        assert_eq!(val.unwrap(), 1);
    }

}

<|endoftext|>


<commit_before>/*!

Suffix Array Construction

worst time: O(N)
worst space: N bytes (for input) + N words (for suffix array)

# Credit
Ge Nong and the team:
https://code.google.com/p/ge-nong/

*/

use std::{iter, vec};
use compress::bwt;

pub type Symbol = u8;
pub type Suffix = uint;

static EMPTY: Suffix = 0x7FFFFFFF;

fn get_buckets(input: &[Symbol], buckets: &mut [uint], end: bool) {
	for buck in buckets.mut_iter() {
		*buck = 0;
	}
	for sym in input.iter() {
		buckets[*sym] += 1;
	}
	let mut sum = 0u;
	for buck in buckets.mut_iter() {
		sum += *buck;
		*buck = if end {sum} else {sum - *buck};
	}
}

fn put_substr0(_suffixes: &mut [Suffix], input: &[Symbol], buckets: &mut [uint]) {
	// Find the end of each bucket.
	get_buckets(input, buckets, true);

	//TODO
}

fn induce_l0(_suffixes: &mut [Suffix], _input: &[Symbol], _buckets: &mut [uint], _clean: bool) {
	//TODO
}

fn induce_s0(_suffixes: &mut [Suffix], _input: &[Symbol], _buckets: &mut [uint], _clean: bool) {
	//TODO
}

fn gather_lms(suffixes: &mut [Suffix], input: &[Suffix]) {
	//TODO

	for suf in suffixes.mut_iter() {
		*suf = input[*suf];
	}
}

fn put_suffix0(suffixes: &mut [Suffix], n1: uint, input: &[Symbol], buckets: &mut [uint]) {
	// Find the end of each bucket.
	get_buckets(input, buckets, true);

	for i in range(0,n1).rev() {
		let p = suffixes[i];
		suffixes[i] = 0;
		let sym = input[p];
		buckets[sym] -= 1;
		suffixes[buckets[sym]] = p;
	}

	// Set the single sentinel suffix.
	suffixes[0] = input.len()-1;
}

fn name_substr(_suffixes: &mut [Suffix], _input: &[Symbol], _new_input: &[Suffix], _level: uint) -> uint {
	0 //TODO
}

fn saca_kn(input: &[Suffix], suffixes: &mut [Suffix], _level: uint) {
	//TODO

	let n1 = 0u;

	assert!(n1+n1 <= input.len());
	let (sa_new, input_new) = suffixes.mut_split_at(n1);
	//TODO

	// Stage 3: induce SA(S) from SA(S1).
	gather_lms(sa_new, input_new);
	for s in input_new.mut_iter() {
		*s = EMPTY;
	}

	//TODO
}

fn saca_k0(input: &[Symbol], K: uint, suffixes: &mut [Suffix]) {
	let mut buckets = vec::from_elem(K, 0u);

	// Stage 1: reduce the problem by at least 1/2.
	put_substr0(suffixes, input, buckets.as_mut_slice());
	induce_l0(suffixes, input, buckets.as_mut_slice(), false);
	induce_s0(suffixes, input, buckets.as_mut_slice(), false);

	// Now, all the LMS-substrings are sorted and stored sparsely in SA.
	// Compact all the sorted substrings into the first n1 items of SA.
	let mut n1 = 0u;
	for i in range(0, suffixes.len()) {
		if suffixes[i]>0 {
			suffixes[n1] = suffixes[i];
			n1 += 1;
		}
	}

	// Stage 2: solve the reduced problem.
	{
		assert!(n1+n1 <= input.len());
		let (sa_new, input_new) = suffixes.mut_split_at(n1);
		let num_names = name_substr(sa_new, input, input_new, 0);

		if num_names < n1 {
			// Recurse if names are not yet unique.
			saca_kn(input_new, sa_new, 1);
		}else {
			// Get the suffix array of s1 directly.
			for (i,&sym) in input_new.iter().enumerate() {
				sa_new[sym] = i;
			}
		}

		// Stage 3: induce SA(S) from SA(S1).
		gather_lms(sa_new, input_new);
		for s in input_new.mut_iter() {
			*s = 0;
		}
	}

	put_suffix0(suffixes, n1, input, buckets.as_mut_slice());
	induce_l0(suffixes, input, buckets.as_mut_slice(), true);
	induce_s0(suffixes, input, buckets.as_mut_slice(), true);
}

/// main entry point for SAC
pub fn construct_suffix_array(input: &[Symbol], suffixes: &mut [Suffix]) {
	assert_eq!(input.len(), suffixes.len());
	for (i,p) in suffixes.mut_iter().enumerate() {
		*p = i as Suffix;
	}

	if true {
		saca_k0(input, 0x100, suffixes);
	}else {
		suffixes.sort_by(|&a,&b| {
			iter::order::cmp(
				input.slice_from(a).iter(),
				input.slice_from(b).iter())
		});
	}

	debug!("construct suf: {:?}", suffixes);
}

/// An iterator over BWT output
pub struct LastColumnIterator<'a> {
	priv input		: &'a [Symbol],
	priv suf_iter	: iter::Enumerate<vec::Items<'a,Suffix>>,
	priv origin		: Option<uint>,
}

impl<'a> LastColumnIterator<'a> {
	/// create a new BWT iterator from the suffix array
	pub fn new(input: &'a [Symbol], suffixes: &'a [Suffix]) -> LastColumnIterator<'a> {
		LastColumnIterator {
			input: input,
			suf_iter: suffixes.iter().enumerate(),
			origin: None,
		}
	}

	/// return the index of the original string
	pub fn get_origin(&self) -> uint {
		self.origin.unwrap()
	}
}

impl<'a> Iterator<Symbol> for LastColumnIterator<'a> {
	fn next(&mut self) -> Option<Symbol> {
		self.suf_iter.next().map(|(i,&p)| {
			if p == 0 {
				assert!( self.origin.is_none() );
				self.origin = Some(i);
				*self.input.last().unwrap()
			}else {
				self.input[p-1]
			}
		})
	}
}

/// A helper method to perform BWT on a given block and place the result into output
/// returns the original string index in the sorted matrix
pub fn BW_transform(input: &[Symbol], suf: &mut [Suffix], output: &mut [Symbol]) -> uint {
	construct_suffix_array(input, suf);
	let mut iter = LastColumnIterator::new(input, suf);
	for (out,s) in output.mut_iter().zip(iter.by_ref()) {
		*out = s;
	}
	iter.get_origin()
}

/// An iterator over inverse BWT
pub struct InverseIterator<'a> {
	priv input		: &'a [Symbol],
	priv suffixes	: &'a [Suffix],
	priv origin		: Suffix,
	priv current	: Suffix,
}

impl<'a> InverseIterator<'a> {
	/// create a new inverse BWT iterator
	pub fn new(input: &'a [Symbol], origin: uint, suffixes: &'a mut [Suffix]) -> InverseIterator<'a> {
		assert_eq!(input.len(), suffixes.len())
		debug!("decode origin={}, input: {:?}", origin, input)

		let mut radix = bwt::Radix::new();
		radix.gather(input);
		radix.accumulate();

		suffixes[radix.place(input[origin])] = 0;
		for (i,&ch) in input.slice_to(origin).iter().enumerate() {
			suffixes[radix.place(ch)] = i+1;
		}
		for (i,&ch) in input.slice_from(origin+1).iter().enumerate() {
			suffixes[radix.place(ch)] = origin+2+i;
		}
		//suffixes[-1] = origin;
		debug!("decode table: {:?}", suffixes)

		InverseIterator {
			input: input,
			suffixes: suffixes,
			origin: origin,
			current: origin as Suffix,
		}
	}
}

impl<'a> Iterator<Symbol> for InverseIterator<'a> {
	fn next(&mut self) -> Option<Symbol> {
		if self.current == -1 {
			None
		}else {
			self.current = self.suffixes[self.current] - 1;
			debug!("\tjumped to {}", self.current);
			let p = if self.current!=-1 {self.current} else {self.origin};
			Some(self.input[p])
		}
	}
}

#[cfg(test)]
pub mod test {
	use std::{mem, vec};
	use super::{EMPTY, Suffix, Symbol};

	#[test]
	fn consts() {
		assert_eq!(EMPTY, 1<<(mem::size_of::<Suffix>()*8-1));
	}

	#[test]
	fn abracadabra() {
		let input = bytes!("abracadabra");
		let mut suf = vec::from_elem(input.len(), 0 as Suffix);
		super::construct_suffix_array(input, suf);
		assert_eq!(suf.as_slice(), &[10,7,0,3,5,8,1,4,6,9,2]);
		let (output, origin) = {
			let mut iter = super::LastColumnIterator::new(input,suf);
			let out = iter.by_ref().take(input.len()).to_owned_vec();
			(out, iter.get_origin())
		};
		assert_eq!(origin, 2);
		let expected = bytes!("rdarcaaaabb");
		assert_eq!(output.as_slice(), expected.as_slice());
		let decoded = super::InverseIterator::new(output, origin, suf).to_owned_vec();
		assert_eq!(input.as_slice(), decoded.as_slice());
	}

	#[test]
	fn roundtrip() {
		let input = include_bin!("../LICENSE");
		let mut suf = vec::from_elem(input.len(), 0 as Suffix);
		let mut output = vec::from_elem(input.len(), 0 as Symbol);
		let origin = super::BW_transform(input, suf, output);
		let decoded = super::InverseIterator::new(output, origin, suf).
			take(input.len()).to_owned_vec();
		assert_eq!(input.as_slice(), decoded.as_slice());
	}
}
<commit_msg>SACA - put_str0, induce_l0, induce_s0, type conversion is improved<commit_after>/*!

Suffix Array Construction

worst time: O(N)
worst space: N bytes (for input) + N words (for suffix array)

# Credit
Ge Nong and the team:
https://code.google.com/p/ge-nong/

*/

use std::{iter, vec};
use compress::bwt;

pub type Symbol = u8;
pub type Suffix = u32;

static EMPTY: Suffix = 0x80000000;

fn get_buckets(input: &[Symbol], buckets: &mut [uint], end: bool) {
	for buck in buckets.mut_iter() {
		*buck = 0;
	}
	for sym in input.iter() {
		buckets[*sym] += 1;
	}
	let mut sum = 0u;
	for buck in buckets.mut_iter() {
		sum += *buck;
		*buck = if end {sum} else {sum - *buck};
	}
}

fn put_substr0(suffixes: &mut [Suffix], input: &[Symbol], buckets: &mut [uint]) {
	// Find the end of each bucket.
	get_buckets(input, buckets, true);

	// Set each item in SA as empty.
	for suf in suffixes.mut_iter() {
		*suf = 0;
	}

	// Last string is L-type
	input.iter().zip(input.slice_from(1).iter()).enumerate().rev().fold(false, |succ_t, (i,(&prev,&cur))| {
		if prev < cur || (prev==cur && succ_t) {
			true
		}else {
			if succ_t {
				buckets[cur] -= 1;
				suffixes[buckets[cur]] = i as Suffix;
			}
			false
		}
	});

	// Set the single sentinel LMS-substring.
	*suffixes.mut_last().unwrap() = (input.len()-1) as Suffix;
}

fn induce_l0(suffixes: &mut [Suffix], input: &[Symbol], buckets: &mut [uint], clean: bool) {
	// Find the head of each bucket.
	get_buckets(input, buckets, false);

	buckets[0]+=1; // skip the virtual sentinel.

	for i in range(0,suffixes.len()) {
		let suf = suffixes[i];
		if suf > 0 {
			let sym = input[suf-1];
			if sym >= input[suf] {
				suffixes[buckets[sym]] = suf-1;
				buckets[sym] += 1;
				if clean && i>0 {
					suffixes[i] = 0;
				}
			}
		}
	}
}

fn induce_s0(suffixes: &mut [Suffix], input: &[Symbol], buckets: &mut [uint], clean: bool) {
	// Find the head of each bucket.
	get_buckets(input, buckets, true);

	for i in range(1,suffixes.len()).rev() {
		let suf = suffixes[i];
		if suf > 0 {
			let sym = input[suf-1];
			if sym <= input[suf] && buckets[sym] < i {
				buckets[sym] -= 1;
				suffixes[buckets[sym]] = suf-1;
				if clean {
					suffixes[i] = 0;
				}
			}
		}
	}
}

fn gather_lms(suffixes: &mut [Suffix], input: &[Suffix]) {
	//TODO

	for suf in suffixes.mut_iter() {
		*suf = input[*suf];
	}
}

fn put_suffix0(suffixes: &mut [Suffix], n1: uint, input: &[Symbol], buckets: &mut [uint]) {
	// Find the end of each bucket.
	get_buckets(input, buckets, true);

	for i in range(0,n1).rev() {
		let p = suffixes[i];
		suffixes[i] = 0;
		let sym = input[p];
		buckets[sym] -= 1;
		suffixes[buckets[sym]] = p;
	}

	// Set the single sentinel suffix.
	suffixes[0] = (input.len()-1) as Suffix;
}

fn name_substr(_suffixes: &mut [Suffix], _input: &[Symbol], _new_input: &[Suffix], _level: uint) -> uint {
	0 //TODO
}

fn saca_kn(input: &[Suffix], suffixes: &mut [Suffix], _level: uint) {
	//TODO

	let n1 = 0u;

	assert!(n1+n1 <= input.len());
	let (sa_new, input_new) = suffixes.mut_split_at(n1);
	//TODO

	// Stage 3: induce SA(S) from SA(S1).
	gather_lms(sa_new, input_new);
	for s in input_new.mut_iter() {
		*s = EMPTY;
	}

	//TODO
}

fn saca_k0(input: &[Symbol], K: uint, suffixes: &mut [Suffix]) {
	let mut buckets = vec::from_elem(K, 0u);

	// Stage 1: reduce the problem by at least 1/2.
	put_substr0(suffixes, input, buckets.as_mut_slice());
	induce_l0(suffixes, input, buckets.as_mut_slice(), true);
	induce_s0(suffixes, input, buckets.as_mut_slice(), true);

	// Now, all the LMS-substrings are sorted and stored sparsely in SA.
	// Compact all the sorted substrings into the first n1 items of SA.
	let mut n1 = 0u;
	for i in range(0, suffixes.len()) {
		if suffixes[i]>0 {
			suffixes[n1] = suffixes[i];
			n1 += 1;
		}
	}

	// Stage 2: solve the reduced problem.
	{
		assert!(n1+n1 <= input.len());
		let (sa_new, input_new) = suffixes.mut_split_at(n1);
		let num_names = name_substr(sa_new, input, input_new, 0);

		if num_names < n1 {
			// Recurse if names are not yet unique.
			saca_kn(input_new, sa_new, 1);
		}else {
			// Get the suffix array of s1 directly.
			for (i,&sym) in input_new.iter().enumerate() {
				sa_new[sym] = i as Suffix;
			}
		}

		// Stage 3: induce SA(S) from SA(S1).
		gather_lms(sa_new, input_new);
		for s in input_new.mut_iter() {
			*s = 0;
		}
	}

	put_suffix0(suffixes, n1, input, buckets.as_mut_slice());
	induce_l0(suffixes, input, buckets.as_mut_slice(), false);
	induce_s0(suffixes, input, buckets.as_mut_slice(), false);
}

/// main entry point for SAC
pub fn construct_suffix_array(input: &[Symbol], suffixes: &mut [Suffix]) {
	assert_eq!(input.len(), suffixes.len());
	for (i,p) in suffixes.mut_iter().enumerate() {
		*p = i as Suffix;
	}

	if true {
		saca_k0(input, 0x100, suffixes);
	}else {
		suffixes.sort_by(|&a,&b| {
			iter::order::cmp(
				input.slice_from(a as uint).iter(),
				input.slice_from(b as uint).iter())
		});
	}

	debug!("construct suf: {:?}", suffixes);
}

/// An iterator over BWT output
pub struct LastColumnIterator<'a> {
	priv input		: &'a [Symbol],
	priv suf_iter	: iter::Enumerate<vec::Items<'a,Suffix>>,
	priv origin		: Option<uint>,
}

impl<'a> LastColumnIterator<'a> {
	/// create a new BWT iterator from the suffix array
	pub fn new(input: &'a [Symbol], suffixes: &'a [Suffix]) -> LastColumnIterator<'a> {
		LastColumnIterator {
			input: input,
			suf_iter: suffixes.iter().enumerate(),
			origin: None,
		}
	}

	/// return the index of the original string
	pub fn get_origin(&self) -> uint {
		self.origin.unwrap()
	}
}

impl<'a> Iterator<Symbol> for LastColumnIterator<'a> {
	fn next(&mut self) -> Option<Symbol> {
		self.suf_iter.next().map(|(i,&p)| {
			if p == 0 {
				assert!( self.origin.is_none() );
				self.origin = Some(i);
				*self.input.last().unwrap()
			}else {
				self.input[p-1]
			}
		})
	}
}

/// A helper method to perform BWT on a given block and place the result into output
/// returns the original string index in the sorted matrix
pub fn BW_transform(input: &[Symbol], suf: &mut [Suffix], output: &mut [Symbol]) -> uint {
	construct_suffix_array(input, suf);
	let mut iter = LastColumnIterator::new(input, suf);
	for (out,s) in output.mut_iter().zip(iter.by_ref()) {
		*out = s;
	}
	iter.get_origin()
}

/// An iterator over inverse BWT
pub struct InverseIterator<'a> {
	priv input		: &'a [Symbol],
	priv suffixes	: &'a [Suffix],
	priv origin		: uint,
	priv current	: Suffix,
}

impl<'a> InverseIterator<'a> {
	/// create a new inverse BWT iterator
	pub fn new(input: &'a [Symbol], origin: uint, suffixes: &'a mut [Suffix]) -> InverseIterator<'a> {
		assert_eq!(input.len(), suffixes.len())
		debug!("decode origin={}, input: {:?}", origin, input)

		let mut radix = bwt::Radix::new();
		radix.gather(input);
		radix.accumulate();

		suffixes[radix.place(input[origin])] = 0;
		for (i,&ch) in input.slice_to(origin).iter().enumerate() {
			suffixes[radix.place(ch)] = (i+1) as Suffix;
		}
		for (i,&ch) in input.slice_from(origin+1).iter().enumerate() {
			suffixes[radix.place(ch)] = (origin+2+i) as Suffix;
		}
		//suffixes[-1] = origin;
		debug!("decode table: {:?}", suffixes)

		InverseIterator {
			input: input,
			suffixes: suffixes,
			origin: origin,
			current: origin as Suffix,
		}
	}
}

impl<'a> Iterator<Symbol> for InverseIterator<'a> {
	fn next(&mut self) -> Option<Symbol> {
		if self.current == -1 {
			None
		}else {
			self.current = self.suffixes[self.current] - 1;
			debug!("\tjumped to {}", self.current);
			let p = if self.current!=-1 {
				self.current
			}else {
				self.origin as Suffix
			};
			Some(self.input[p])
		}
	}
}

#[cfg(test)]
pub mod test {
	use std::{mem, vec};
	use super::{EMPTY, Suffix, Symbol};

	#[test]
	fn consts() {
		assert_eq!(EMPTY, 1<<(mem::size_of::<Suffix>()*8-1));
	}

	#[test]
	fn abracadabra() {
		let input = bytes!("abracadabra");
		let mut suf = vec::from_elem(input.len(), 0 as Suffix);
		super::construct_suffix_array(input, suf);
		assert_eq!(suf.as_slice(), &[10,7,0,3,5,8,1,4,6,9,2]);
		let (output, origin) = {
			let mut iter = super::LastColumnIterator::new(input,suf);
			let out = iter.by_ref().take(input.len()).to_owned_vec();
			(out, iter.get_origin())
		};
		assert_eq!(origin, 2);
		let expected = bytes!("rdarcaaaabb");
		assert_eq!(output.as_slice(), expected.as_slice());
		let decoded = super::InverseIterator::new(output, origin, suf).to_owned_vec();
		assert_eq!(input.as_slice(), decoded.as_slice());
	}

	#[test]
	fn roundtrip() {
		let input = include_bin!("../LICENSE");
		let mut suf = vec::from_elem(input.len(), 0 as Suffix);
		let mut output = vec::from_elem(input.len(), 0 as Symbol);
		let origin = super::BW_transform(input, suf, output);
		let decoded = super::InverseIterator::new(output, origin, suf).
			take(input.len()).to_owned_vec();
		assert_eq!(input.as_slice(), decoded.as_slice());
	}
}
<|endoftext|>


<commit_before>extern crate stun;

use std::net::SocketAddr;

pub fn get_mapped_address(local_addr: SocketAddr) -> Result<SocketAddr, String> {
    let local_port = local_addr.port();
    let ip_version = match local_addr {
        SocketAddr::V4(_) => stun::IpVersion::V4,
        SocketAddr::V6(_) => stun::IpVersion::V6
    };
    let client = stun::Client::new("stun.l.google.com:19302", local_port, ip_version);
    let mesage = stun::Message::request();
    let response = client.send(mesage.encode());
    let stun::Message { attributes, ..} = stun::Message::decode(response);

    if let stun::Attribute::XorMappedAddress(stun::XorMappedAddress(address)) = attributes[0] {
        Ok(address)
    } else {
        Err(format!("Couldn't resolve mapped adress"))
    }
}
<commit_msg>Randomly use a STUN server from a static set<commit_after>extern crate stun;
extern crate rand;

use rand::Rng;
use std::net::SocketAddr;

// TODO: These should be part of configuration
const STUN_SERVERS: &'static [&'static str] = &[
    "stun.l.google.com:19302",
    "stun1.l.google.com:19302",
    "stun2.l.google.com:19302",
    "stun3.l.google.com:19302",
    "stun4.l.google.com:19302"
];

pub fn get_mapped_address(local_addr: SocketAddr) -> Result<SocketAddr, String> {
    let stun_server = rand::thread_rng().choose(STUN_SERVERS).expect("No STUN server");
    let local_port = local_addr.port();
    let ip_version = match local_addr {
        SocketAddr::V4(_) => stun::IpVersion::V4,
        SocketAddr::V6(_) => stun::IpVersion::V6
    };
    let client = stun::Client::new(stun_server, local_port, ip_version);
    let mesage = stun::Message::request();
    let response = client.send(mesage.encode());
    let stun::Message { attributes, ..} = stun::Message::decode(response);

    if let stun::Attribute::XorMappedAddress(stun::XorMappedAddress(address)) = attributes[0] {
        Ok(address)
    } else {
        Err(format!("Couldn't resolve mapped adress"))
    }
}
<|endoftext|>