<commit_before>extern crate iron;
extern crate router;
extern crate params;
extern crate serde;
extern crate serde_json;
extern crate url;
extern crate mote;
extern crate rgb;

#[macro_use]
extern crate serde_derive;

#[macro_use]
extern crate maplit;

use std::io::Read;
use std::sync::Mutex;

use iron::headers::ContentType;
use iron::middleware::Handler;
use iron::modifiers::Redirect;
use iron::prelude::{Iron, IronResult, Request, Response};
use iron::prelude::*;
use iron::status;
use router::Router;
use url::Url;

mod google_actions;
use google_actions::*;

mod smart_home;
use smart_home::*;

struct Hub {
    devices: Mutex<Vec<Device>>,
}

impl Handler for Hub {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        println!("hub handler");
        let mut body = String::new();
        req.body.read_to_string(&mut body).unwrap();
        let action_request: ActionRequest = serde_json::from_str(&body).unwrap();

        println!("action_request: {:?}", action_request);

        for input in action_request.inputs {
            if input.intent == "action.devices.SYNC" {
                let mut response = SyncResponse {
                    request_id: action_request.request_id.clone(),
                    payload: SyncResponsePayload {
                        agent_user_id: "1111".to_string(),
                        devices: vec![],
                    },
                };

                let ref devices = *self.devices.lock().unwrap();
                for device in devices {
                    match device {
                        &Device::Light(ref light) => {
                            response.payload.devices.push(SyncResponseDevice {
                                id: light.id.clone(),
                                type_: light.type_.name(),
                                traits: light.available_light_modes
                                    .iter()
                                    .map(LightMode::name)
                                    .collect(),
                                name: Name {
                                    default_name: vec![light.name.to_string()],
                                    name: Some(light.name.clone()),
                                    nicknames: vec![],
                                },
                                will_report_state: false,
                                device_info: None,
                                room_hint: None,
                                structure_hint: None,
                            })
                        }
                        &Device::Thermostat(ref thermostat) => {
                            response.payload.devices.push(SyncResponseDevice {
                                id: thermostat.id.clone(),
                                type_: "".to_string(), // XXX
                                traits: vec!["action.devices.traits.TemperatureSetting"
                                                 .to_string()],
                                name: Name {
                                    default_name: vec![thermostat.name.to_string()],
                                    name: Some(thermostat.name.clone()),
                                    nicknames: vec![],
                                },
                                // TODO: attributes.
                                will_report_state: false,
                                device_info: None,
                                room_hint: None,
                                structure_hint: None,
                            })
                        }
                    }
                }

                let res = serde_json::to_string(&response).unwrap_or("".to_string());
                println!("action_response: {:?}", res);
                let mut rsp = Response::with((status::Ok, res));
                rsp.headers.set(ContentType::json());
                return Ok(rsp);
            } else if input.intent == "action.devices.QUERY" {
                let mut response = QueryResponse {
                    request_id: action_request.request_id.clone(),
                    payload: QueryResponsePayload { devices: btreemap!{} },
                };

                let ref devices = *self.devices.lock().unwrap();
                if let Some(payload) = input.payload {
                    for request_device in payload.devices {
                        for device in devices {
                            match device {
                                &Device::Light(ref light) => {
                                    if light.id == request_device.id {
                                        response.payload
                                            .devices
                                            .insert(light.id.clone(), light.status.clone().into());
                                    }
                                }
                                &Device::Thermostat(ref thermostat) => {
                                    if thermostat.id == request_device.id {
                                        // TODO
                                    }
                                }
                            }
                        }
                    }
                }

                let res = serde_json::to_string(&response).unwrap_or("".to_string());
                println!("action_response: {:?}", res);
                let mut rsp = Response::with((status::Ok, res));
                rsp.headers.set(ContentType::json());
                return Ok(rsp);
            } else if input.intent == "action.devices.EXECUTE" {
                let mut response = ExecuteResponse {
                    request_id: action_request.request_id.clone(),
                    payload: ExecuteResponsePayload {
                        error_code: None,
                        debug_string: None,
                        commands: vec![],
                    },
                };

                if let Some(ref p) = input.payload {
                    for command in &p.commands {
                        println!("command: {:?}", command);
                        for execution in &command.execution {
                            println!("execution: {:?}", execution);
                            for request_device in &command.devices {
                                println!("request_device: {:?}", request_device);
                                let ref mut devices = *self.devices.lock().unwrap();
                                for device in devices {
                                    match device {
                                        &mut Device::Light(ref mut light) => {
                                            if light.id == request_device.id {
                                                if let Some(s) = execution.params.on {
                                                    light.set_on(s);
                                                }
                                                if let Some(s) = execution.params.brightness {
                                                    light.set_brightness(s);
                                                }
                                                if let Some(ref s) = execution.params.color {
                                                    if let Some(s) = s.spectrum_rgb {
                                                        light.set_color(to_rgb(s));
                                                    }
                                                }
                                                response.payload
                                                    .commands
                                                    .push(ExecuteResponseCommand {
                                                        ids: vec![light.id.clone()],
                                                        status: "SUCCESS".to_string(),
                                                        states: light.status.clone().into(),
                                                    });
                                            }
                                        }
                                        &mut Device::Thermostat(ref mut thermostat) => {
                                            if thermostat.id == request_device.id {
                                                if let Some(s) = execution.params
                                                    .thermostat_temperature_setpoint {
                                                    thermostat.temperature_setpoint(s);
                                                }
                                                if let (Some(low), Some(high)) =
                                                    (execution.params
                                                         .thermostat_temperature_setpoint_low,
                                                     execution.params
                                                         .thermostat_temperature_setpoint_high) {
                                                    thermostat.temperature_set_range(low, high);
                                                }
                                                if let Some(ref mode) = execution.params
                                                    .thermostat_mode {
                                                    if let Some(mode) =
                                                        ThermostatMode::from_name(mode) {
                                                        thermostat.thermostat_set_mode(mode);
                                                    }
                                                }
                                                response.payload
                                                    .commands
                                                    .push(ExecuteResponseCommand {
                                                        ids: vec![thermostat.id.clone()],
                                                        status: "SUCCESS".to_string(),
                                                        states: thermostat.status.clone().into(),
                                                    });
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                let res = serde_json::to_string(&response).unwrap_or("".to_string());
                println!("action_response: {:?}", res);
                let mut rsp = Response::with((status::Ok, res));
                rsp.headers.set(ContentType::json());
                return Ok(rsp);
            }
        }

        let mut rsp = Response::with((status::Ok, "ACTION"));
        rsp.headers.set(ContentType::json());
        Ok(rsp)
    }
}

fn to_rgb(c: u64) -> rgb::RGB8 {
    rgb::RGB8 {
        r: ((c & 0xFF0000) >> 16) as u8,
        g: ((c & 0x00FF00) >> 8) as u8,
        b: ((c & 0x0000FF) >> 0) as u8,
    }
}

fn main() {
    let hub = Hub {
        devices: Mutex::new(vec![Device::Light(Light {
                                     id: "11".to_string(),
                                     name: "TV lights".to_string(),
                                     status: LightStatus::default(),
                                     type_: LightType::Light,
                                     available_light_modes: vec![LightMode::OnOff,
                                                                 LightMode::Brightness,
                                                                 LightMode::ColorSpectrum],
                                     mote: mote::Mote::new("/dev/ttyACM0"),
                                 })]),
    };
    let mut control = Router::new();
    control.get("/auth", auth_handler, "auth")
        .post("/token", token_handler, "token")
        .get("/login", login_handler, "login")
        .post("/action", hub, "post action")
        .get("/action", get_action_handler, "get action")
        .get("/", index_handler, "index");
    println!("Listening on port 1234");
    Iron::new(control)
        .http("0.0.0.0:1234")
        .unwrap();
}

fn auth_handler(req: &mut Request) -> IronResult<Response> {
    let map = req.get_ref::<params::Params>().unwrap();

    let _ = map.find(&["response_type"]);
    let _ = map.find(&["client_id"]);
    let redirect_uri = map.find(&["redirect_uri"]);
    let scope = map.find(&["scope"]);
    let state = map.find(&["state"]);

    println!("uri: {:?}", redirect_uri);
    println!("scope: {:?}", scope);

    let s = match state {
        Some(&params::Value::String(ref x)) => x,
        _ => "",
    };

    let u = match redirect_uri {
        Some(&params::Value::String(ref x)) => {
            let mut url = Url::parse(&x).unwrap();
            url.set_query(Some(&format!("code=123&state={}", s)));
            url
        }
        _ => Url::parse("").unwrap(),
    };

    let uu = iron::Url::from_generic_url(u).unwrap();

    Ok(Response::with((status::Found, Redirect(uu))))
}

fn token_handler(req: &mut Request) -> IronResult<Response> {
    let map = req.get_ref::<params::Params>().unwrap();

    let _ = map.find(&["grant_type"]);
    let _ = map.find(&["code"]);
    let _ = map.find(&["redirect_uri"]);
    let _ = map.find(&["client_id"]);

    let auth_response = AuthResponse {
        token_type: "bearer".to_string(),
        access_token: "xxx".to_string(),
        refresh_token: "yyy".to_string(),
        expires_in: 1000000,
    };

    let res = serde_json::to_string(&auth_response).unwrap_or("".to_string());

    Ok(Response::with((status::Ok, res)))
}

fn login_handler(req: &mut Request) -> IronResult<Response> {
    let map = req.get_ref::<params::Params>().unwrap();

    let _ = map.find(&["username"]);
    let _ = map.find(&["password"]);

    Ok(Response::with((status::Ok, "login")))
}

fn index_handler(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "index")))
}

fn get_action_handler(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "get action")))
}
<commit_msg>oauth struct<commit_after>extern crate iron;
extern crate router;
extern crate params;
extern crate serde;
extern crate serde_json;
extern crate url;
extern crate mote;
extern crate rgb;

#[macro_use]
extern crate serde_derive;

#[macro_use]
extern crate maplit;

use std::io::Read;
use std::sync::Mutex;

use iron::headers::ContentType;
use iron::middleware::Handler;
use iron::modifiers::Redirect;
use iron::prelude::{Iron, IronResult, Request, Response};
use iron::prelude::*;
use iron::status;
use router::Router;
use url::Url;

mod google_actions;
use google_actions::*;

mod smart_home;
use smart_home::*;

struct OAuth {
    auth: OAuthAuth,
    token: OAuthToken,
}

impl OAuth {
    fn new() -> OAuth {
        OAuth {
            auth: OAuthAuth {},
            token: OAuthToken {},
        }
    }
}

struct OAuthAuth {}

impl Handler for OAuthAuth {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let map = req.get_ref::<params::Params>().unwrap();

        let _ = map.find(&["response_type"]);
        let _ = map.find(&["client_id"]);
        let redirect_uri = map.find(&["redirect_uri"]);
        let scope = map.find(&["scope"]);
        let state = map.find(&["state"]);

        println!("uri: {:?}", redirect_uri);
        println!("scope: {:?}", scope);

        let s = match state {
            Some(&params::Value::String(ref x)) => x,
            _ => "",
        };

        let u = match redirect_uri {
            Some(&params::Value::String(ref x)) => {
                let mut url = Url::parse(&x).unwrap();
                url.set_query(Some(&format!("code=123&state={}", s)));
                url
            }
            _ => Url::parse("").unwrap(),
        };

        let uu = iron::Url::from_generic_url(u).unwrap();

        Ok(Response::with((status::Found, Redirect(uu))))
    }
}

struct OAuthToken {}

impl Handler for OAuthToken {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let map = req.get_ref::<params::Params>().unwrap();

        let _ = map.find(&["grant_type"]);
        let _ = map.find(&["code"]);
        let _ = map.find(&["redirect_uri"]);
        let _ = map.find(&["client_id"]);

        let auth_response = AuthResponse {
            token_type: "bearer".to_string(),
            access_token: "xxx".to_string(),
            refresh_token: "yyy".to_string(),
            expires_in: 1000000,
        };

        let res = serde_json::to_string(&auth_response).unwrap_or("".to_string());

        Ok(Response::with((status::Ok, res)))
    }
}

struct Hub {
    devices: Mutex<Vec<Device>>,
}

impl Handler for Hub {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        println!("hub handler");
        let mut body = String::new();
        req.body.read_to_string(&mut body).unwrap();
        let action_request: ActionRequest = serde_json::from_str(&body).unwrap();

        println!("action_request: {:?}", action_request);

        for input in action_request.inputs {
            if input.intent == "action.devices.SYNC" {
                let mut response = SyncResponse {
                    request_id: action_request.request_id.clone(),
                    payload: SyncResponsePayload {
                        agent_user_id: "1111".to_string(),
                        devices: vec![],
                    },
                };

                let ref devices = *self.devices.lock().unwrap();
                for device in devices {
                    match device {
                        &Device::Light(ref light) => {
                            response.payload.devices.push(SyncResponseDevice {
                                id: light.id.clone(),
                                type_: light.type_.name(),
                                traits: light.available_light_modes
                                    .iter()
                                    .map(LightMode::name)
                                    .collect(),
                                name: Name {
                                    default_name: vec![light.name.to_string()],
                                    name: Some(light.name.clone()),
                                    nicknames: vec![],
                                },
                                will_report_state: false,
                                device_info: None,
                                room_hint: None,
                                structure_hint: None,
                            })
                        }
                        &Device::Thermostat(ref thermostat) => {
                            response.payload.devices.push(SyncResponseDevice {
                                id: thermostat.id.clone(),
                                type_: "".to_string(), // XXX
                                traits: vec!["action.devices.traits.TemperatureSetting"
                                                 .to_string()],
                                name: Name {
                                    default_name: vec![thermostat.name.to_string()],
                                    name: Some(thermostat.name.clone()),
                                    nicknames: vec![],
                                },
                                // TODO: attributes.
                                will_report_state: false,
                                device_info: None,
                                room_hint: None,
                                structure_hint: None,
                            })
                        }
                    }
                }

                let res = serde_json::to_string(&response).unwrap_or("".to_string());
                println!("action_response: {:?}", res);
                let mut rsp = Response::with((status::Ok, res));
                rsp.headers.set(ContentType::json());
                return Ok(rsp);
            } else if input.intent == "action.devices.QUERY" {
                let mut response = QueryResponse {
                    request_id: action_request.request_id.clone(),
                    payload: QueryResponsePayload { devices: btreemap!{} },
                };

                let ref devices = *self.devices.lock().unwrap();
                if let Some(payload) = input.payload {
                    for request_device in payload.devices {
                        for device in devices {
                            match device {
                                &Device::Light(ref light) => {
                                    if light.id == request_device.id {
                                        response.payload
                                            .devices
                                            .insert(light.id.clone(), light.status.clone().into());
                                    }
                                }
                                &Device::Thermostat(ref thermostat) => {
                                    if thermostat.id == request_device.id {
                                        // TODO
                                    }
                                }
                            }
                        }
                    }
                }

                let res = serde_json::to_string(&response).unwrap_or("".to_string());
                println!("action_response: {:?}", res);
                let mut rsp = Response::with((status::Ok, res));
                rsp.headers.set(ContentType::json());
                return Ok(rsp);
            } else if input.intent == "action.devices.EXECUTE" {
                let mut response = ExecuteResponse {
                    request_id: action_request.request_id.clone(),
                    payload: ExecuteResponsePayload {
                        error_code: None,
                        debug_string: None,
                        commands: vec![],
                    },
                };

                if let Some(ref p) = input.payload {
                    for command in &p.commands {
                        println!("command: {:?}", command);
                        for execution in &command.execution {
                            println!("execution: {:?}", execution);
                            for request_device in &command.devices {
                                println!("request_device: {:?}", request_device);
                                let ref mut devices = *self.devices.lock().unwrap();
                                for device in devices {
                                    match device {
                                        &mut Device::Light(ref mut light) => {
                                            if light.id == request_device.id {
                                                if let Some(s) = execution.params.on {
                                                    light.set_on(s);
                                                }
                                                if let Some(s) = execution.params.brightness {
                                                    light.set_brightness(s);
                                                }
                                                if let Some(ref s) = execution.params.color {
                                                    if let Some(s) = s.spectrum_rgb {
                                                        light.set_color(to_rgb(s));
                                                    }
                                                }
                                                response.payload
                                                    .commands
                                                    .push(ExecuteResponseCommand {
                                                        ids: vec![light.id.clone()],
                                                        status: "SUCCESS".to_string(),
                                                        states: light.status.clone().into(),
                                                    });
                                            }
                                        }
                                        &mut Device::Thermostat(ref mut thermostat) => {
                                            if thermostat.id == request_device.id {
                                                if let Some(s) = execution.params
                                                    .thermostat_temperature_setpoint {
                                                    thermostat.temperature_setpoint(s);
                                                }
                                                if let (Some(low), Some(high)) =
                                                    (execution.params
                                                         .thermostat_temperature_setpoint_low,
                                                     execution.params
                                                         .thermostat_temperature_setpoint_high) {
                                                    thermostat.temperature_set_range(low, high);
                                                }
                                                if let Some(ref mode) = execution.params
                                                    .thermostat_mode {
                                                    if let Some(mode) =
                                                        ThermostatMode::from_name(mode) {
                                                        thermostat.thermostat_set_mode(mode);
                                                    }
                                                }
                                                response.payload
                                                    .commands
                                                    .push(ExecuteResponseCommand {
                                                        ids: vec![thermostat.id.clone()],
                                                        status: "SUCCESS".to_string(),
                                                        states: thermostat.status.clone().into(),
                                                    });
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                let res = serde_json::to_string(&response).unwrap_or("".to_string());
                println!("action_response: {:?}", res);
                let mut rsp = Response::with((status::Ok, res));
                rsp.headers.set(ContentType::json());
                return Ok(rsp);
            }
        }

        let mut rsp = Response::with((status::Ok, "ACTION"));
        rsp.headers.set(ContentType::json());
        Ok(rsp)
    }
}

fn to_rgb(c: u64) -> rgb::RGB8 {
    rgb::RGB8 {
        r: ((c & 0xFF0000) >> 16) as u8,
        g: ((c & 0x00FF00) >> 8) as u8,
        b: ((c & 0x0000FF) >> 0) as u8,
    }
}

fn main() {
    let hub = Hub {
        devices: Mutex::new(vec![Device::Light(Light {
                                     id: "11".to_string(),
                                     name: "TV lights".to_string(),
                                     status: LightStatus::default(),
                                     type_: LightType::Light,
                                     available_light_modes: vec![LightMode::OnOff,
                                                                 LightMode::Brightness,
                                                                 LightMode::ColorSpectrum],
                                     mote: mote::Mote::new("/dev/ttyACM0"),
                                 })]),
    };
    let oauth = OAuth::new();
    let mut control = Router::new();
    control.get("/auth", oauth.auth, "auth")
        .post("/token", oauth.token, "token")
        .get("/login", login_handler, "login")
        .post("/action", hub, "post action")
        .get("/action", get_action_handler, "get action")
        .get("/", index_handler, "index");
    println!("Listening on port 1234");
    Iron::new(control)
        .http("0.0.0.0:1234")
        .unwrap();
}

fn login_handler(req: &mut Request) -> IronResult<Response> {
    let map = req.get_ref::<params::Params>().unwrap();

    let _ = map.find(&["username"]);
    let _ = map.find(&["password"]);

    Ok(Response::with((status::Ok, "login")))
}

fn index_handler(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "index")))
}

fn get_action_handler(_: &mut Request) -> IronResult<Response> {
    Ok(Response::with((status::Ok, "get action")))
}
<|endoftext|>


<commit_before>extern crate image;
extern crate time;

use std::path::Path;
use image::{GenericImage, ImageBuffer, Rgba};
use std::ops::Sub;
use time::*;

fn main() {
    let img = image::open(&Path::new("test.png")).unwrap();
    let mut palette: Vec<Rgba<u8>> = Vec::new();

    let (width, height) = img.dimensions();

    let total_pixels = img.pixels().count();
    let mut current_pixel = 1;

    let start = time::now();
    for pixel in img.pixels() {
        let (_,_,pix) = pixel;
        if is_unique(&mut palette, &pix) {
            // println!("pixel: {:?}", pixel);
            palette.push(pix.clone());
        }
        let percentage = (current_pixel * 100) / total_pixels;
        print!("\r{}% | {} / {}", percentage, current_pixel, total_pixels);
        current_pixel += 1;
    }
    println!("");

    gen_palette(&mut palette);

    let end = time::now();
    let total_time = end.sub(start);
    println!("color: {:?}", img.color());
    println!("width: {:?}, height: {:?}", width, height);
    println!("number of total pixels:  {}", width * height);
    //println!("{:?} - {:?}", start, end);
    println!("total time: {:?}", total_time);
}

fn is_unique(palette: &mut Vec<Rgba<u8>>, pixel: &Rgba<u8>) -> bool {
    let mut does_exist: bool = false;
    for pix in palette.iter() {
        if pix == pixel {
            does_exist = true;
        }
    }
    !does_exist
}

fn gen_palette(palette: &mut Vec<Rgba<u8>>) -> () {
    let width:u32;
    let height: u32;

    match palette.len() {
        0...2 => {
            width = 2;
            height = 2;
        },
        _ => {
            let length = palette.len() as f32;
            width = length.sqrt().ceil() as u32;
            height = length.sqrt().ceil() as u32;
        }
    }

    let mut new_img = ImageBuffer::new(width, height);

    for y in 0..height {
        for x in 0..width {
            match palette.pop() {
                Some(s) => new_img.put_pixel(x, y, s),
                _ => continue
            }
        }
    }

    let _ = new_img.save(&Path::new("test_palette.png"));
}
<commit_msg>Switched from Vec to HashSet<commit_after>extern crate image;
extern crate time;

use std::path::Path;
use std::collections::HashSet;
use image::{GenericImage, ImageBuffer, Rgba};
use std::ops::Sub;
use time::*;

fn main() {
    let img = image::open(&Path::new("test.png")).unwrap();
    let mut palette:HashSet<Rgba<u8>> = HashSet::new();

    let (width, height) = img.dimensions();

    let total_pixels = img.pixels().count();
    let mut current_pixel = 1;

    let start = time::now();
    for pixel in img.pixels() {
        let (_,_,pix) = pixel;
        palette.insert(pix);
        let percentage = (current_pixel * 100) / total_pixels;
        print!("\r{}% | {} / {}", percentage, current_pixel, total_pixels);
        current_pixel += 1;
    }
    println!("");

    gen_palette(&mut palette);

    let end = time::now();
    let total_time = end.sub(start);
    println!("color: {:?}", img.color());
    println!("width: {:?}, height: {:?}", width, height);
    println!("number of total pixels:  {}", width * height);
    println!("total time: {:?}", total_time);
}

fn gen_palette(palette: &mut HashSet<Rgba<u8>>) -> () {
    let size:u32;

    match palette.len() {
        0...2 => {
            size = 2;
        },
        _ => {
            let length = palette.len() as f32;
            size = length.sqrt().ceil() as u32;
        }
    }

    let mut new_img = ImageBuffer::new(size, size);

    let mut current_x:u32 = 0;
    let mut current_y:u32 = 0;

    for pix in palette.iter() {
        new_img.put_pixel(current_x, current_y, pix.clone());
        current_x += 1;
        if current_x == size {
            current_x = 0;
            current_y += 1;
        }
    }

    let _ = new_img.save(&Path::new("test_palette.png"));
}
<|endoftext|>


<commit_before><commit_msg>Refactor Pixel struct<commit_after><|endoftext|>


<commit_before>extern crate fuse;
extern crate libc;
extern crate time;
extern crate hyper;
extern crate rustc_serialize;
extern crate clap;

use std::collections::BTreeMap;
use std::path::Path;
use std::env;
use std::io::prelude::Read;
use libc::{ENOENT, ENOSYS};
use time::Timespec;
use fuse::{FileAttr, FileType, Filesystem, Request, ReplyAttr, ReplyData, ReplyEntry, ReplyDirectory, ReplyOpen};
use hyper::client::{Client, Response};
use rustc_serialize::json::Json;
use clap::{App, Arg};

struct TwitchFileSystem {
    attrs: BTreeMap<u64, FileAttr>,
    inodes: BTreeMap<String, u64>,
    urls: BTreeMap<u64, String>
}

impl TwitchFileSystem {
    fn new() -> TwitchFileSystem {
        let mut attrs = BTreeMap::new();
        let mut inodes = BTreeMap::new();
        let mut urls = BTreeMap::new();

        let ts = time::now().to_timespec();
        let attr = FileAttr {
            ino: 1,
            size: 0,
            blocks: 0,
            atime: ts,
            mtime: ts,
            ctime: ts,
            crtime: ts,
            kind: FileType::Directory,
            perm: 0o755,
            nlink: 0,
            uid: 0,
            gid: 0,
            rdev: 0,
            flags: 0
        };
        attrs.insert(1, attr);
        inodes.insert("/".to_owned(), 1);
        let mut body = String::new();
        Client::new()
            .get("https://api.twitch.tv/kraken/streams/featured")
            .send()
            .expect("Couldn't load twitch")
            .read_to_string(&mut body);

        match Json::from_str(&body) {
            Ok(data) => {
                let streams = data.find("featured").unwrap().as_array().unwrap();
                for (i, stream) in streams.iter().enumerate() {
                    let game = stream
                        .find_path(&["stream", "game"])
                        .unwrap()
                        .as_string()
                        .unwrap();

                    let name = stream
                        .find_path(&["stream", "channel", "display_name"])
                        .unwrap()
                        .as_string()
                        .unwrap();

                    let url = stream
                        .find_path(&["stream", "channel", "url"])
                        .unwrap()
                        .as_string()
                        .unwrap()
                        .to_owned();

                    let attr = FileAttr {
                        ino: i as u64 + 2,
                        size: url.len() as u64,
                        blocks: 1,
                        atime: ts,
                        mtime: ts,
                        ctime: ts,
                        crtime: ts,
                        kind: FileType::RegularFile,
                        perm: 0o644,
                        nlink: 0,
                        uid: 0,
                        gid: 0,
                        rdev: 0,
                        flags: 0
                    };

                    attrs.insert(attr.ino, attr);
                    inodes.insert(format!("{} - {}", name, game), attr.ino);
                    urls.insert(attr.ino, url);
                }
            },
            Err(_) => println!("Twitch returned invalid json")
        }
        TwitchFileSystem {attrs: attrs, inodes: inodes, urls: urls}
    }
}

impl Filesystem for TwitchFileSystem {
    fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        match self.attrs.get(&ino) {
            Some(attr) => {
                let ttl = Timespec::new(1, 0);
                reply.attr(&ttl, attr);
            },
            None => reply.error(ENOENT)
        }
    }

    fn lookup(&mut self, _req: &Request, parent: u64, name: &Path, reply: ReplyEntry) {
        let inode = match self.inodes.get(name.to_str().unwrap()) {
            Some(inode) => inode,
            None => {
                reply.error(ENOENT);
                return;
            }
        };
        match self.attrs.get(inode) {
            Some(attr) => {
                let ttl = Timespec::new(1, 0);
                reply.entry(&ttl, attr, 0);
            },
            None => reply.error(ENOENT),
        };
    }

    fn readdir(&mut self, _req: &Request, ino: u64, fh: u64, offset: u64, mut reply: ReplyDirectory) {
        if offset == 0 {
            if ino == 1 {
                for (stream, &inode) in &self.inodes {
                    if inode == 1 { continue; }
                    let offset = inode;
                    reply.add(inode, offset, FileType::RegularFile, &Path::new(stream));
                }
                reply.add(1, 0, FileType::Directory, &Path::new("."));
                reply.add(1, 1, FileType::Directory, &Path::new(".."));
            }
        }

        reply.ok();
    }
    fn read(&mut self, _req: &Request, ino: u64, fh: u64, offset: u64, size: u32, reply: ReplyData) {
        if self.urls.contains_key(&ino) {
            reply.data(self.urls.get(&ino).unwrap().as_bytes());
            return;
        }
        reply.error(ENOSYS);
    }
}

fn is_valid_dir(mountpoint: String) -> Result<(), String> {
    match Path::new(&mountpoint).is_dir() {
        true => Ok(()),
        false => Err("Mountpoint must be a directory".to_string()),
    }
}

fn main() {
    let matches = App::new("twitch-fs")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("unknown version"))
        .arg(Arg::with_name("mountpoint")
             .validator(is_valid_dir)
             .index(1)
             .required(true))
        .get_matches();

    // unwrap() is safe here because the argument is set as required
    let mountpoint = matches.value_of_os("mountpoint").unwrap();
    let fs = TwitchFileSystem::new();

    fuse::mount(fs , &mountpoint, &[])
}
<commit_msg>Fix issue with panic on game being null<commit_after>extern crate fuse;
extern crate libc;
extern crate time;
extern crate hyper;
extern crate rustc_serialize;
extern crate clap;

use std::collections::BTreeMap;
use std::path::Path;
use std::env;
use std::io::prelude::Read;
use libc::{ENOENT, ENOSYS};
use time::Timespec;
use fuse::{FileAttr, FileType, Filesystem, Request, ReplyAttr, ReplyData, ReplyEntry, ReplyDirectory, ReplyOpen};
use hyper::client::{Client, Response};
use rustc_serialize::json::Json;
use clap::{App, Arg};

struct TwitchFileSystem {
    attrs: BTreeMap<u64, FileAttr>,
    inodes: BTreeMap<String, u64>,
    urls: BTreeMap<u64, String>
}

impl TwitchFileSystem {
    fn new() -> TwitchFileSystem {
        let mut attrs = BTreeMap::new();
        let mut inodes = BTreeMap::new();
        let mut urls = BTreeMap::new();

        let ts = time::now().to_timespec();
        let attr = FileAttr {
            ino: 1,
            size: 0,
            blocks: 0,
            atime: ts,
            mtime: ts,
            ctime: ts,
            crtime: ts,
            kind: FileType::Directory,
            perm: 0o755,
            nlink: 0,
            uid: 0,
            gid: 0,
            rdev: 0,
            flags: 0
        };
        attrs.insert(1, attr);
        inodes.insert("/".to_owned(), 1);
        let mut body = String::new();
        Client::new()
            .get("https://api.twitch.tv/kraken/streams/featured")
            .send()
            .expect("Couldn't load twitch")
            .read_to_string(&mut body);

        match Json::from_str(&body) {
            Ok(data) => {
                let streams = data.find("featured").unwrap().as_array().unwrap();
                for (i, stream) in streams.iter().enumerate() {
                    let game = stream
                        .find_path(&["stream", "game"])
                        .unwrap()
                        .as_string()
                        .unwrap_or("");

                    let name = stream
                        .find_path(&["stream", "channel", "display_name"])
                        .unwrap()
                        .as_string()
                        .unwrap();

                    let url = stream
                        .find_path(&["stream", "channel", "url"])
                        .unwrap()
                        .as_string()
                        .unwrap()
                        .to_owned();

                    let attr = FileAttr {
                        ino: i as u64 + 2,
                        size: url.len() as u64,
                        blocks: 1,
                        atime: ts,
                        mtime: ts,
                        ctime: ts,
                        crtime: ts,
                        kind: FileType::RegularFile,
                        perm: 0o644,
                        nlink: 0,
                        uid: 0,
                        gid: 0,
                        rdev: 0,
                        flags: 0
                    };

                    attrs.insert(attr.ino, attr);
                    inodes.insert(format!("{} - {}", name, game), attr.ino);
                    urls.insert(attr.ino, url);
                }
            },
            Err(_) => println!("Twitch returned invalid json")
        }
        TwitchFileSystem {attrs: attrs, inodes: inodes, urls: urls}
    }
}

impl Filesystem for TwitchFileSystem {
    fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        match self.attrs.get(&ino) {
            Some(attr) => {
                let ttl = Timespec::new(1, 0);
                reply.attr(&ttl, attr);
            },
            None => reply.error(ENOENT)
        }
    }

    fn lookup(&mut self, _req: &Request, parent: u64, name: &Path, reply: ReplyEntry) {
        let inode = match self.inodes.get(name.to_str().unwrap()) {
            Some(inode) => inode,
            None => {
                reply.error(ENOENT);
                return;
            }
        };
        match self.attrs.get(inode) {
            Some(attr) => {
                let ttl = Timespec::new(1, 0);
                reply.entry(&ttl, attr, 0);
            },
            None => reply.error(ENOENT),
        };
    }

    fn readdir(&mut self, _req: &Request, ino: u64, fh: u64, offset: u64, mut reply: ReplyDirectory) {
        if offset == 0 {
            if ino == 1 {
                for (stream, &inode) in &self.inodes {
                    if inode == 1 { continue; }
                    let offset = inode;
                    reply.add(inode, offset, FileType::RegularFile, &Path::new(stream));
                }
                reply.add(1, 0, FileType::Directory, &Path::new("."));
                reply.add(1, 1, FileType::Directory, &Path::new(".."));
            }
        }

        reply.ok();
    }
    fn read(&mut self, _req: &Request, ino: u64, fh: u64, offset: u64, size: u32, reply: ReplyData) {
        if self.urls.contains_key(&ino) {
            reply.data(self.urls.get(&ino).unwrap().as_bytes());
            return;
        }
        reply.error(ENOSYS);
    }
}

fn is_valid_dir(mountpoint: String) -> Result<(), String> {
    match Path::new(&mountpoint).is_dir() {
        true => Ok(()),
        false => Err("Mountpoint must be a directory".to_string()),
    }
}

fn main() {
    let matches = App::new("twitch-fs")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("unknown version"))
        .arg(Arg::with_name("mountpoint")
             .validator(is_valid_dir)
             .index(1)
             .required(true))
        .get_matches();

    // unwrap() is safe here because the argument is set as required
    let mountpoint = matches.value_of_os("mountpoint").unwrap();
    let fs = TwitchFileSystem::new();

    fuse::mount(fs , &mountpoint, &[])
}
<|endoftext|>


<commit_before><commit_msg>Remove try!()<commit_after><|endoftext|>


<commit_before>extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Hello to the guessing game!");

    let std_in = io::stdin();

    let number_to_guess = rand::thread_rng().gen_range(1, 101);

    loop {
        println!("Please enter a number: ");
        let mut guess = String::new();
        std_in.read_line(&mut guess).expect("Failed to read line.");
        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => {
                println!("Please enter a valid number");
                continue;
            }
        };

        match guess.cmp(&number_to_guess) {
            Ordering::Less => println!("Too small"),
            Ordering::Equal => {
                println!("Correct!");
                break;
            },
            Ordering::Greater => println!("Too big"),
        }
    }
}
<commit_msg>Add maximum attempts<commit_after>extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("Hello to the guessing game!");

    let std_in = io::stdin();

    let number_to_guess = rand::thread_rng().gen_range(1, 101);

    const MAX_TRIES: u32 = 6;
    let mut tries = 0;

    loop {
        if tries == MAX_TRIES {
            println!("Too many tries, you lose :/");
            break;
        }

        println!("Please enter a number: ");
        let mut guess = String::new();
        std_in.read_line(&mut guess).expect("Failed to read line.");
        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => {
                println!("Please enter a valid number");
                continue;
            }
        };

        match guess.cmp(&number_to_guess) {
            Ordering::Less => println!("Too small"),
            Ordering::Equal => {
                println!("Correct!");
                break;
            },
            Ordering::Greater => println!("Too big"),
        }
        tries += 1;
    }
}
<|endoftext|>


<commit_before><commit_msg>fill: avoid needless_borrow Clippy warning<commit_after><|endoftext|>


<commit_before><commit_msg>Use macros to reduce duplication in some of the tests. (Is this really worth it? Macros are not super-readable and the test runner doesn't give the right lines).<commit_after><|endoftext|>


<commit_before><commit_msg>Use video title as file name when downloading<commit_after><|endoftext|>


<commit_before><commit_msg>Improve documentation.<commit_after><|endoftext|>


<commit_before>extern crate osmpbfreader;
extern crate time;

use time::PreciseTime;
use std::fs::File;
use std::path::Path;
use std::ffi::OsString;
use std::collections::HashMap;
use std::collections::HashSet;

use osmpbfreader::OsmObj;
use osmpbfreader::OsmPbfReader;

#[derive(Debug, Clone, Copy)]
struct Position {
    lat: f64,
    lon: f64,
}

#[derive(Debug, Clone, Copy)]
struct RoutingEdge {
    id_from: i64,
    id_to: i64,
    length: f64
}

struct FirstParseResult {
    // used node-ids
    nodes_used: HashSet<i64>,
    // "useful" ways
    filtered_ways: HashSet<i64>
}

struct SecondParseResult {
    // relevant nodes and their position
    nodes: HashMap<i64, Position>,
}

struct ThirdParseResult {
    // edges
    edges: Vec<RoutingEdge>
}

struct RoutingData {
    // relevant nodes and their position
    osm_nodes: HashMap<i64, Position>,
    //[n_id] -> osm_n_id
    internal_nodes: Vec<i64>,
    // [e_id] -> osm_n_id target
    internal_edges: Vec<i64>,
    // [n_id] -> e_id
    internal_offset: Vec<i64>,
    // e_id -> length
    internal_length: Vec<f64>
}

fn main() {
    let default_file = OsString::from("/home/zsdn/germany-latest.osm.pbf".to_string());
    let args: Vec<OsString> = std::env::args_os().collect();
    match args.len() {
        1 => {
            read_file(&default_file);
        }
        2 => {
            read_file(&args[1]);
        }
        _ => {},
    };
}

fn read_file(filename: &OsString) {
    let start_p1 = PreciseTime::now();
    let firstParseResult = first_parse(&filename);
    let end_p1 = PreciseTime::now();

    println!("P1 | ways:  {}", firstParseResult.filtered_ways.len());
    println!("P1 | nodes: {}", firstParseResult.nodes_used.len());
    println!("P1 | duration: {}", start_p1.to(end_p1));

    let start_p2 = PreciseTime::now();
    let secondParseResult = second_parse(&filename, &firstParseResult);
    let end_p2 = PreciseTime::now();

    println!("P2 | nodes: {}", secondParseResult.nodes.len());
    println!("P2 | duration: {}", start_p2.to(end_p2));

    let start_p3 = PreciseTime::now();
    let thirdParseResult = third_parse(&filename, &firstParseResult, &secondParseResult);
    let end_p3 = PreciseTime::now();

    println!("P3 | edges:  {}", thirdParseResult.edges.len());
    println!("P3 | duration: {}", start_p3.to(end_p3));
}

fn first_parse(filename: &OsString) -> FirstParseResult {
    let pbf_file = File::open(&Path::new(filename)).unwrap();
    let mut result = FirstParseResult { nodes_used: HashSet::new(), filtered_ways: HashSet::new() };

    let mut invalid_values = HashSet::new();
    init_filter_list(&mut invalid_values);

    let mut pbf = OsmPbfReader::new(pbf_file);

    for obj in pbf.iter() {
        match obj {
            OsmObj::Way(way) => {
                if filter_way(&way, &invalid_values) {
                    for node in way.nodes {
                        result.nodes_used.insert(node);
                    }
                    result.filtered_ways.insert(way.id);
                }
            }
            _ => {}
        }
    }

    return result;
}

fn second_parse(filename: &OsString, input: &FirstParseResult) -> SecondParseResult {
    let pbf_file = File::open(&Path::new(filename)).unwrap();
    let mut pbf = OsmPbfReader::new(pbf_file);
    let mut result = SecondParseResult { nodes: HashMap::new() };

    for obj in pbf.iter() {
        match obj {
            OsmObj::Node(node) => {
                if input.nodes_used.contains(&node.id) {
                    result.nodes.insert(node.id, Position { lat: node.lat, lon: node.lon });
                }
            }
            _ => {}
        }
    }

    return result;
}

fn third_parse(filename: &OsString, first: &FirstParseResult, second: &SecondParseResult) -> ThirdParseResult {
    let pbf_file = File::open(&Path::new(filename)).unwrap();
    let mut pbf = OsmPbfReader::new(pbf_file);
    let mut result = ThirdParseResult { edges: Vec::new() };

    for obj in pbf.iter() {
        match obj {
            OsmObj::Way(way) => {
                if first.filtered_ways.contains(&way.id) {
                    for node_pair in way.nodes.windows(2) {
                        if let (Some(from), Some(to)) = (node_pair.first(), node_pair.last()) {
                            if let (Some(from_node), Some(to_node)) = (second.nodes.get(from), second.nodes.get(to)) {
                                let edge_length = calculate_distance(from_node, to_node);
                                let edge = RoutingEdge { id_from: from.clone(), id_to: to.clone(), length: edge_length.clone() };
                                result.edges.push(edge);

                                if let Some(val) = way.tags.get("oneway") {
                                    if val == "yes" {
                                        let edge_reverse = RoutingEdge { id_from: to.clone(), id_to: from.clone(), length: edge_length.clone() };
                                        result.edges.push(edge_reverse);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            _ => {}
        }
    }

    return result;
}

fn calculate_distance(node1: &Position, node2: &Position) -> f64 {
    let lat1 = node1.lat;
    let lat2 = node2.lat;
    let lng1 = node1.lon;
    let lng2 = node2.lon;

    let earth_radius: f64 = 6371000.0; //meters
    let d_lat = (lat2 - lat1).to_radians();
    let d_lng = (lng2 - lng1).to_radians();
    let a = (d_lat / 2.0).sin() * (d_lat / 2.0).sin() + lat1.to_radians().cos() * lat2.to_radians().cos() * (d_lng / 2.0).sin() * (d_lng / 2.0).sin();
    let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt());
    let dist = earth_radius * c;

    return dist;
}

fn init_filter_list(invalid_values: &mut HashSet<&str>) {
    invalid_values.insert("services");
    invalid_values.insert("pedestrian");
    invalid_values.insert("raceway");
    invalid_values.insert("footway");
    invalid_values.insert("path");
    invalid_values.insert("steps");
    invalid_values.insert("bridleway");
    invalid_values.insert("construction");
}

fn filter_way(way: &osmpbfreader::Way, invalid_values: &HashSet<&str>) -> bool {
    if let Some(value) = way.tags.get("highway") {
        return !invalid_values.contains(&value.as_str());
    } else {
        return false;
    }
}<commit_msg>improved parsing space usage, changed default map from ger to ger.bw, implemented conversion to offset array<commit_after>extern crate osmpbfreader;
extern crate time;

use time::PreciseTime;
use std::fs::File;
use std::path::Path;
use std::ffi::OsString;
use std::collections::HashMap;
use std::collections::HashSet;

use osmpbfreader::OsmObj;
use osmpbfreader::OsmPbfReader;

#[derive(Debug, Clone, Copy)]
struct Position {
    lat: f64,
    lon: f64,
}

#[derive(Debug, Clone, Copy)]
struct ParsedEdge {
    id_from: i64,
    id_to: i64,
    length: f64,
}

struct ParseData {
    // used node-ids
    nodes_used: HashSet<i64>,
    // "useful" ways
    filtered_ways: HashSet<i64>,
    // relevant nodes and their position
    nodes: HashMap<i64, Position>,
    // edges
    edges: Vec<ParsedEdge>
}

struct RoutingEdge {
    target: usize,
    length: f64,
    constraints: u8,
}

struct OsmNode {
    position: Position,
    internal_id: usize
}

struct RoutingData {
    // relevant nodes and their position
    osm_nodes: HashMap<i64, OsmNode>,
    //[n_id] -> osm_n_id
    internal_nodes: Vec<i64>,
    // [e_id] -> n_id target|length|constraints
    internal_edges: Vec<RoutingEdge>,
    // [n_id] -> e_id
    internal_offset: Vec<usize>,
}

fn main() {
    let default_file = OsString::from("/home/zsdn/baden-wuerttemberg-latest.osm.pbf".to_string());
    let args: Vec<OsString> = std::env::args_os().collect();
    match args.len() {
        1 => {
            read_file(&default_file);
        }
        2 => {
            read_file(&args[1]);
        }
        _ => {},
    };
}

fn read_file(filename: &OsString) -> RoutingData {
    let mut parse_result = ParseData { nodes_used: HashSet::new(), filtered_ways: HashSet::new(), nodes: HashMap::new(), edges: Vec::new() };

    let start_p1 = PreciseTime::now();
    first_parse(&filename, &mut parse_result);
    let end_p1 = PreciseTime::now();

    println!("P1 | ways:  {}", parse_result.filtered_ways.len());
    println!("P1 | nodes: {}", parse_result.nodes_used.len());
    println!("P1 | duration: {}", start_p1.to(end_p1));

    let start_p2 = PreciseTime::now();
    second_parse(&filename, &mut parse_result);
    let end_p2 = PreciseTime::now();

    println!("P2 | nodes: {}", parse_result.nodes.len());
    println!("P2 | duration: {}", start_p2.to(end_p2));

    let start_p3 = PreciseTime::now();
    third_parse(&filename, &mut parse_result);
    let end_p3 = PreciseTime::now();

    println!("P3 | edges:  {}", parse_result.edges.len());
    println!("P3 | duration: {}", start_p3.to(end_p3));

    let start_b = PreciseTime::now();
    let routing_data = build_routing_data(&mut parse_result);
    let end_b = PreciseTime::now();

    println!("B  | edges:  {}", routing_data.internal_edges.len());
    println!("B  | nodes:  {}", routing_data.internal_nodes.len());
    println!("B  | offset:  {}", routing_data.internal_offset.len());
    println!("B  | osm_nodes:  {}", routing_data.osm_nodes.len());
    println!("B  | duration: {}", start_b.to(end_b));

    return routing_data;
}

fn first_parse(filename: &OsString, parse_result: &mut ParseData) {
    let pbf_file = File::open(&Path::new(filename)).unwrap();

    let mut invalid_values = HashSet::new();
    init_filter_list(&mut invalid_values);

    let mut pbf = OsmPbfReader::new(pbf_file);

    for obj in pbf.iter() {
        match obj {
            OsmObj::Way(way) => {
                if filter_way(&way, &invalid_values) {
                    for node in way.nodes {
                        parse_result.nodes_used.insert(node);
                    }
                    parse_result.filtered_ways.insert(way.id);
                }
            }
            _ => {}
        }
    }
}

fn second_parse(filename: &OsString, parse_result: &mut ParseData) {
    let pbf_file = File::open(&Path::new(filename)).unwrap();
    let mut pbf = OsmPbfReader::new(pbf_file);

    for obj in pbf.iter() {
        match obj {
            OsmObj::Node(node) => {
                if parse_result.nodes_used.remove(&node.id) {
                    parse_result.nodes.insert(node.id, Position { lat: node.lat, lon: node.lon });
                }
            }
            _ => {}
        }
    }
}

fn third_parse(filename: &OsString, parse_result: &mut ParseData) {
    let pbf_file = File::open(&Path::new(filename)).unwrap();
    let mut pbf = OsmPbfReader::new(pbf_file);

    for obj in pbf.iter() {
        match obj {
            OsmObj::Way(way) => {
                if parse_result.filtered_ways.remove(&way.id) {
                    for node_pair in way.nodes.windows(2) {
                        if let (Some(from), Some(to)) = (node_pair.first(), node_pair.last()) {
                            if let (Some(from_node), Some(to_node)) = (parse_result.nodes.get(from), parse_result.nodes.get(to)) {
                                let edge_length = calculate_distance(from_node, to_node);
                                let edge = ParsedEdge { id_from: from.clone(), id_to: to.clone(), length: edge_length.clone() };
                                parse_result.edges.push(edge);

                                if let Some(val) = way.tags.get("oneway") {
                                    if val == "yes" {
                                        let edge_reverse = ParsedEdge { id_from: to.clone(), id_to: from.clone(), length: edge_length.clone() };
                                        parse_result.edges.push(edge_reverse);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            _ => {}
        }
    }
}

fn build_routing_data(parse_result: &mut ParseData) -> RoutingData {
    let mut routing_data = RoutingData { osm_nodes: HashMap::new(), internal_nodes: Vec::new(), internal_edges: Vec::new(), internal_offset: vec![usize::max_value(); parse_result.nodes.len()] };

    parse_result.edges.sort_by(|a, b| b.id_from.cmp(&a.id_from));

    for node in parse_result.nodes.keys() {
        routing_data.internal_nodes.push(node.clone());
    }

    routing_data.internal_nodes.sort();

    for (i, node) in routing_data.internal_nodes.iter().enumerate() {
        if let Some(pos) = parse_result.nodes.remove(node) {
            routing_data.osm_nodes.insert(node.clone(), OsmNode { position: pos, internal_id: i });

            routing_data.internal_offset.push(routing_data.internal_edges.len());

            loop {
                let mut relevant_edge = false;
                if let Some(edge) = parse_result.edges.last() {
                    if edge.id_from == *node {
                        relevant_edge = true;
                    }
                }
                if relevant_edge {
                    if let Some(edge) = parse_result.edges.pop() {
                        routing_data.internal_edges.push(RoutingEdge { target: edge.id_to as usize, length: edge.length, constraints: 0b00000001 });
                    }
                }
            }
        }
    }

    return routing_data;
}

fn calculate_distance(node1: &Position, node2: &Position) -> f64 {
    let lat1 = node1.lat;
    let lat2 = node2.lat;
    let lng1 = node1.lon;
    let lng2 = node2.lon;

    let earth_radius: f64 = 6371000.0; //meters
    let d_lat = (lat2 - lat1).to_radians();
    let d_lng = (lng2 - lng1).to_radians();
    let a = (d_lat / 2.0).sin() * (d_lat / 2.0).sin() + lat1.to_radians().cos() * lat2.to_radians().cos() * (d_lng / 2.0).sin() * (d_lng / 2.0).sin();
    let c = 2.0 * a.sqrt().atan2((1.0 - a).sqrt());
    let dist = earth_radius * c;

    return dist;
}

fn init_filter_list(invalid_values: &mut HashSet<&str>) {
    invalid_values.insert("services");
    invalid_values.insert("pedestrian");
    invalid_values.insert("raceway");
    invalid_values.insert("footway");
    invalid_values.insert("path");
    invalid_values.insert("steps");
    invalid_values.insert("bridleway");
    invalid_values.insert("construction");
}

fn filter_way(way: &osmpbfreader::Way, invalid_values: &HashSet<&str>) -> bool {
    if let Some(value) = way.tags.get("highway") {
        return !invalid_values.contains(&value.as_str());
    } else {
        return false;
    }
}<|endoftext|>


<commit_before><commit_msg>improve documentation<commit_after><|endoftext|>


<commit_before><commit_msg>Remove unnecessary markers<commit_after><|endoftext|>


<commit_before>fn main(expr: &str) -> f32 {
  let mut stack:Vec<f32> = Vec::new();
  for token in expr.split_whitespace() {
    let wrapped_operand = token.parse::<f32>();
    let is_operator = wrapped_operand.is_err();
    if is_operator {
      if stack.len() < 2 {
        panic!("Unsufficient operands before operator");
      }
      // xxxFlorent: Any way to destructure like this? Not sure of what I am doing below
      // let [ operand1, operand2 ] = stack.drain((token.len() - 3)..).collect();
      let operand2 = stack.pop().expect("expected f32 values only in stack");
      let operand1 = stack.pop().expect("expected f32 values only in stack");
      let result = match token {
        "+" => operand1 + operand2,
        "-" => operand1 - operand2,
        "*" => operand1 * operand2,
        "/" => operand1 / operand2,
        _ => panic!("Unsupported operator")
      };
      stack.push(result);
    } else {
      stack.push(wrapped_operand.unwrap());
    }
  }

  if stack.len() != 1 {
    panic!("Remaining untreated operands. Probably missing operator.");
  }
  return stack.pop().expect("expected a f32 value remaining in stack");
}

#[test]
fn it_adds() {
  let result = main("1 2 +");
  assert_eq!(result, 3.0);
}

#[test]
fn it_substracts() {
  let result = main("1 2 -");
  assert_eq!(result, -1.0);
}

#[test]
fn it_multiplies() {
  let result = main("6 7 *");
  assert_eq!(result, 42.0);
}

#[test]
fn it_divides() {
  let result = main("1 2 /");
  assert_eq!(result, 0.5);
}

#[test]
fn it_calculates_complex_expressions() {
  // ((1+2) * 8 / (5-1) - 1) / 2
  let result = main("1 2 + 8 * 5 1 - / 1 - 2 /");
  assert_eq!(result, 2.5);
}

#[test]
fn it_allows_multiple_shitespaces() {
  let result = main("1  2 +\t3 -");
  assert_eq!(result, 0.0);
}

#[test]
#[should_panic]
fn it_panics_for_unsupported_characters() {
  main("1 2 t");
  // xxxFlorent: How to test the panic message is right?
}

#[test]
#[should_panic]
fn it_panics_for_unsufficient_operands() {
  main("1 +");
  // xxxFlorent: How to test the panic message is right?
}

#[test]
#[should_panic]
fn it_panics_for_unsufficient_operators() {
  main("1 2 3 +");
  // xxxFlorent: How to test the panic message is right?
}
<commit_msg>Implement repl<commit_after>use std::io::{self, Write};

fn main() {
  println!("Reverse Polish Notation.");
  println!("Type quit to exit");

  loop {
    print!("> ");
    io::stdout().flush();
    let mut input = String::new();

    io::stdin().read_line(&mut input)
      .expect("failed to read line");

    if input == "quit" {
      break;
    }
    println!("{}", rpl(&input));
  }
}

fn rpl(expr: &str) -> f32 {
  let mut stack:Vec<f32> = Vec::new();
  for token in expr.split_whitespace() {
    let wrapped_operand = token.parse::<f32>();
    let is_operator = wrapped_operand.is_err();
    if is_operator {
      if stack.len() < 2 {
        panic!("Unsufficient operands before operator");
      }
      // xxxFlorent: Any way to destructure like this? Not sure of what I am doing below
      // let [ operand1, operand2 ] = stack.drain((token.len() - 3)..).collect();
      let operand2 = stack.pop().expect("expected f32 values only in stack");
      let operand1 = stack.pop().expect("expected f32 values only in stack");
      let result = match token {
        "+" => operand1 + operand2,
        "-" => operand1 - operand2,
        "*" => operand1 * operand2,
        "/" => operand1 / operand2,
        _ => panic!("Unsupported operator")
      };
      stack.push(result);
    } else {
      stack.push(wrapped_operand.unwrap());
    }
  }

  if stack.len() != 1 {
    panic!("Remaining untreated operands. Probably missing operator.");
  }
  return stack.pop().expect("expected a f32 value remaining in stack");
}

#[test]
fn it_adds() {
  let result = rpl("1 2 +");
  assert_eq!(result, 3.0);
}

#[test]
fn it_substracts() {
  let result = rpl("1 2 -");
  assert_eq!(result, -1.0);
}

#[test]
fn it_multiplies() {
  let result = rpl("6 7 *");
  assert_eq!(result, 42.0);
}

#[test]
fn it_divides() {
  let result = rpl("1 2 /");
  assert_eq!(result, 0.5);
}

#[test]
fn it_calculates_complex_expressions() {
  // ((1+2) * 8 / (5-1) - 1) / 2
  let result = rpl("1 2 + 8 * 5 1 - / 1 - 2 /");
  assert_eq!(result, 2.5);
}

#[test]
fn it_allows_multiple_shitespaces() {
  let result = rpl("1  2 +\t3 -");
  assert_eq!(result, 0.0);
}

#[test]
#[should_panic]
fn it_panics_for_unsupported_characters() {
  rpl("1 2 t");
  // xxxFlorent: How to test the panic message is right?
}

#[test]
#[should_panic]
fn it_panics_for_unsufficient_operands() {
  rpl("1 +");
  // xxxFlorent: How to test the panic message is right?
}

#[test]
#[should_panic]
fn it_panics_for_unsufficient_operators() {
  rpl("1 2 3 +");
  // xxxFlorent: How to test the panic message is right?
}
<|endoftext|>


<commit_before>//! Main module in way-cooler

extern crate rustwlc;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate hlua;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate libc;

use rustwlc::callback;
use rustwlc::interface::WlcInterface;
use rustwlc::types::LogType;

use std::env;

mod registry;
mod keys;
mod callbacks;
mod lua;

/// Callback to route wlc logs into env_logger
extern "C" fn log_handler(level: LogType, message_ptr: *const libc::c_char) {
    let message = unsafe { rustwlc::pointer_to_string(message_ptr) };
    match level {
        LogType::Info => info!("wlc: {}", message),
        LogType::Warn => warn!("wlc: {}", message),
        LogType::Error => error!("wlc: {}", message),
        LogType::Wayland => info!("wayland: {}", message)
    }
}

/// Formats the log strings properly
fn log_format(record: &log::LogRecord) -> String {
    format!("{} [{}] {}", record.level(), record.location().module_path(),
            record.args())
}

fn main() {
    callback::output_created(callbacks::output_created);
    callback::output_destroyed(callbacks::output_destroyed);
    callback::output_focus(callbacks::output_focus);
    callback::output_resolution(callbacks::output_resolution);
        //.output_render_pre(callbacks::output_render_pre)
        //.output_render_post(callbacks::output_render_post)
    callback::view_created(callbacks::view_created);
    callback::view_destroyed(callbacks::view_destroyed);
    callback::view_focus(callbacks::view_focus);
    callback::view_move_to_output(callbacks::view_move_to_output);
    callback::view_request_geometry(callbacks::view_request_geometry);
    callback::view_request_state(callbacks::view_request_state);
    callback::view_request_move(callbacks::view_request_move);
    callback::view_request_resize(callbacks::view_request_resize);
    callback::keyboard_key(callbacks::keyboard_key);
    callback::pointer_button(callbacks::pointer_button);
    callback::pointer_scroll(callbacks::pointer_scroll);
    callback::pointer_motion(callbacks::pointer_motion);
        //.touch_touch(callbacks::touch)
    callback::compositor_ready(callbacks::compositor_ready);
        //.input_created(input_created)
        //.input_destroyed(input_destroyed);

    let mut builder = env_logger::LogBuilder::new();
    builder.format(log_format);
    builder.filter(None, log::LogLevelFilter::Trace);
    if env::var("WAY_COOLER_LOG").is_ok() {
        builder.parse(&env::var("WAY_COOLER_LOG").unwrap());
    }
    builder.init().unwrap();
    info!("Logger initialized, setting wlc handler.");
    rustwlc::log_set_handler(log_handler);

    let run_wlc = rustwlc::init2().expect("Unable to initialize wlc!");

    info!("Started logger");

    run_wlc();
}
<commit_msg>Add extern crate for lua-sys and serialize<commit_after>//! Main module in way-cooler

#[macro_use]
extern crate lazy_static;

extern crate rustwlc;
extern crate libc;

#[macro_use]
extern crate log;
extern crate env_logger;

#[macro_use]
extern crate hlua;
extern crate lua52_sys as hlua_ffi;

extern crate rustc_serialize;

use rustwlc::callback;
use rustwlc::interface::WlcInterface;
use rustwlc::types::LogType;

use std::env;

mod registry;
mod keys;
mod callbacks;
mod lua;

/// Callback to route wlc logs into env_logger
extern "C" fn log_handler(level: LogType, message_ptr: *const libc::c_char) {
    let message = unsafe { rustwlc::pointer_to_string(message_ptr) };
    match level {
        LogType::Info => info!("wlc: {}", message),
        LogType::Warn => warn!("wlc: {}", message),
        LogType::Error => error!("wlc: {}", message),
        LogType::Wayland => info!("wayland: {}", message)
    }
}

/// Formats the log strings properly
fn log_format(record: &log::LogRecord) -> String {
    format!("{} [{}] {}", record.level(), record.location().module_path(),
            record.args())
}

fn main() {
    callback::output_created(callbacks::output_created);
    callback::output_destroyed(callbacks::output_destroyed);
    callback::output_focus(callbacks::output_focus);
    callback::output_resolution(callbacks::output_resolution);
        //.output_render_pre(callbacks::output_render_pre)
        //.output_render_post(callbacks::output_render_post)
    callback::view_created(callbacks::view_created);
    callback::view_destroyed(callbacks::view_destroyed);
    callback::view_focus(callbacks::view_focus);
    callback::view_move_to_output(callbacks::view_move_to_output);
    callback::view_request_geometry(callbacks::view_request_geometry);
    callback::view_request_state(callbacks::view_request_state);
    callback::view_request_move(callbacks::view_request_move);
    callback::view_request_resize(callbacks::view_request_resize);
    callback::keyboard_key(callbacks::keyboard_key);
    callback::pointer_button(callbacks::pointer_button);
    callback::pointer_scroll(callbacks::pointer_scroll);
    callback::pointer_motion(callbacks::pointer_motion);
        //.touch_touch(callbacks::touch)
    callback::compositor_ready(callbacks::compositor_ready);
        //.input_created(input_created)
        //.input_destroyed(input_destroyed);

    let mut builder = env_logger::LogBuilder::new();
    builder.format(log_format);
    builder.filter(None, log::LogLevelFilter::Trace);
    if env::var("WAY_COOLER_LOG").is_ok() {
        builder.parse(&env::var("WAY_COOLER_LOG").unwrap());
    }
    builder.init().unwrap();
    info!("Logger initialized, setting wlc handler.");
    rustwlc::log_set_handler(log_handler);

    let run_wlc = rustwlc::init2().expect("Unable to initialize wlc!");

    info!("Started logger");

    run_wlc();
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate chrono;

use std::env;
use std::fs::DirBuilder;
use std::fs::File;
use std::fs::OpenOptions;
use std::io::Write;
use std::io::Read;
use std::io;
use std::io::Seek;
use std::io::SeekFrom;
use std::ops::Sub;
use std::path::PathBuf;
use std::process;
use std::str;

use clap::{App, AppSettings, SubCommand};

use chrono::DateTime;
use chrono::TimeZone;
use chrono::UTC;

const RECORD_LENGTH: usize = 22;

fn main() {
    match ensure_log_file_exists() {
    	Ok(_) => {},
    	Err(e) => {
    		println!("Couldn't create punch log: {}.\nExiting.", e);
			process::exit(1)
    	}
    }

    let args = App::new("punchcard")
        .about("Time tracker")
        .setting(AppSettings::ArgRequiredElseHelp)
        .subcommand(SubCommand::with_name("in"))
        .subcommand(SubCommand::with_name("out"))
        .subcommand(SubCommand::with_name("card"))
        .get_matches();

	if args.is_present("in") {
		ensure_last_record_is_of_action(Action::PunchOut);
		write_record_to_log(chrono::UTC::now(), Action::PunchIn);
	}

	if args.is_present("out") {
		ensure_last_record_is_of_action(Action::PunchIn);
		write_record_to_log(chrono::UTC::now(), Action::PunchOut);
	}

	if args.is_present("card") {
		print_last_record();
	}
}

#[derive(Debug)]
#[derive(PartialEq)]
enum Action {
	PunchIn,
	PunchOut,
	Unset
}

struct Record {
	timestamp: DateTime<UTC>,
	action: Action
}

fn ensure_last_record_is_of_action(expected_action: Action) {

	let mut config_file = get_conf_file(true, false).unwrap();
    let mut record = empty_record();

    match populate_record_at_offset_from_end(&mut config_file, &mut record, 0) {
    	Ok(_) => {},
    	Err(e) => {
    		println!("Couldn't create punch log: {}.\nExiting.", e);
			process::exit(1)
    	}
    }

    if record.action != expected_action {
    	match expected_action {
    		Action::PunchIn => {
    			println!("Already punched out, punch in first!");
				process::exit(1)
    		}
    		Action::PunchOut => {
    			println!("Already punched in, punch out first!");
    			process::exit(1)
    		}
    		Action::Unset => {
    			println!("Found unset action, log file corrupt");
    			process::exit(1)
    		}
    	}

    }
}

fn get_conf_file(read: bool, append: bool) -> io::Result<File> {

	let mut conf_file = PathBuf::new();
    conf_file.push(env::home_dir().unwrap());
    conf_file.push(".punch");
    conf_file.push("punch.log");

    OpenOptions::new().read(read).append(append).open(conf_file)
}

fn empty_record() -> Record {
	Record {
    	action: Action::Unset,
    	timestamp: chrono::UTC::now()
    }
}

fn print_last_record() {
    let mut config_file = get_conf_file(true, false).unwrap();
    let mut record = empty_record();

    match populate_record_at_offset_from_end(&mut config_file, &mut record, 0) {
    	Ok(_) => {},
    	Err(e) => {
    		println!("Couldn't create punch log: {}.\nExiting.", e);
			process::exit(1)
    	}
    }

    if record.action == Action::PunchIn {
    	let current_timestamp = chrono::UTC::now();
    	let time_punched_in = current_timestamp.sub(record.timestamp);
    	println!("Punched in since {} ({})", record.timestamp, time_punched_in)
    }
    else {
    	let mut previous_record = empty_record();
    	match populate_record_at_offset_from_end(&mut config_file, &mut previous_record, 1) {
	    	Ok(_) => {},
	    	Err(e) => {
	    		println!("Couldn't create punch log: {}.\nExiting.", e);
				process::exit(1)
	    	}
	    }

    	let delta = record.timestamp.sub(previous_record.timestamp);
    	println!("Previously punched in between {} and {} ({})",
    		previous_record.timestamp, record.timestamp, delta)
    }
}

fn populate_record_at_offset_from_end(config_file: &mut File, record: &mut Record, offset_from_end: u64) -> Result<(), String> {
	seek_to_record_offset(config_file, offset_from_end);
	populate_record_at_current_offset(config_file, record);
	Ok(())
}

fn write_record_to_log(tm: DateTime<UTC>, action: Action) {
	let action_token = match action {
		Action::PunchIn => "I",
		Action::PunchOut => "O",
		Action::Unset => "U"
	};

    let mut config_file = get_conf_file(false, true).unwrap();
    let fmt = tm.format("%FT%T");
	let formatted_timestamp = fmt.to_string();
	do_file_write(formatted_timestamp.as_bytes(), &mut config_file);
	do_file_write("_".as_bytes(), &mut config_file);
	do_file_write(action_token.as_bytes(), &mut config_file);
	do_file_write("\n".as_bytes(), &mut config_file);
}

fn populate_record_at_current_offset(f: &mut File, record: &mut Record) -> bool {
	let mut data = [0 as u8; RECORD_LENGTH];
	let read = f.read(&mut data);
	if read.unwrap() != RECORD_LENGTH {
		panic!("Could not read complete record")
	}
	let (ts_data, rest) = data.split_at(19);
	let timestamp = str::from_utf8(&ts_data).unwrap();
	let parse_result = chrono::UTC.datetime_from_str(&timestamp, "%FT%T");

	let record_ts = parse_result.
		unwrap().with_timezone(&chrono::UTC);
	record.timestamp = record_ts;
	let action_string = str::from_utf8(&rest).unwrap();
	if action_string == "_O\n" {
		record.action = Action::PunchOut;
	}
	else if action_string == "_I\n" {
		record.action = Action::PunchIn;
	}
	else {
		panic!("Could not determine action type from '{}'", action_string)
	}
	return true
}

fn seek_to_record_offset(f: &mut File, record_offset: u64) {
	let m = f.metadata().unwrap();
	let file_len = m.len();

	let record_length_in_bytes = RECORD_LENGTH as u64;
	let seek_offset = file_len - ((record_offset + 1) * record_length_in_bytes);

	if f.seek(SeekFrom::Start(seek_offset)).unwrap() != seek_offset {
		panic!("Could not seek to record offset {}", record_offset)
	}
}

fn do_file_write(data: &[u8], f: &mut File) {
	match f.write_all(data) {
    	Ok(_) => {},
    	Err(e) => println!("Failed to write data to log: {}", e)
    }
}

fn ensure_log_file_exists() -> io::Result<()> {
    let mut conf_dir = PathBuf::new();
    conf_dir.push(env::home_dir().unwrap());
    conf_dir.push(".punch");
    let config_path = conf_dir.as_path();

    let mut conf_file_builder = PathBuf::from(config_path);
    conf_file_builder.push("punch.log");

    let mut dir_builder = DirBuilder::new();
    dir_builder.recursive(true);

    try!(dir_builder.create(config_path));

    let conf_file = conf_file_builder.as_path();
    match OpenOptions::new().create(true).write(true).open(conf_file) {
    	Ok(_) => Ok(()),
    	Err(e) => Err(e)
    }
}<commit_msg>shuffle code<commit_after>extern crate clap;
extern crate chrono;

use std::env;
use std::fs::DirBuilder;
use std::fs::File;
use std::fs::OpenOptions;
use std::io::Write;
use std::io::Read;
use std::io;
use std::io::Seek;
use std::io::SeekFrom;
use std::ops::Sub;
use std::path::PathBuf;
use std::process;
use std::str;

use clap::{App, AppSettings, SubCommand};

use chrono::DateTime;
use chrono::TimeZone;
use chrono::UTC;

const RECORD_LENGTH: usize = 22;

#[derive(Debug)]
#[derive(PartialEq)]
enum Action {
	PunchIn,
	PunchOut,
	Unset
}

struct Record {
	timestamp: DateTime<UTC>,
	action: Action
}

fn main() {
    match ensure_log_file_exists() {
    	Ok(_) => {},
    	Err(e) => {
    		println!("Couldn't create punch log: {}.\nExiting.", e);
			process::exit(1)
    	}
    }

    let args = App::new("punchcard")
        .about("Time tracker")
        .setting(AppSettings::ArgRequiredElseHelp)
        .subcommand(SubCommand::with_name("in"))
        .subcommand(SubCommand::with_name("out"))
        .subcommand(SubCommand::with_name("card"))
        .get_matches();

	if args.is_present("in") {
		ensure_last_record_is_of_action(Action::PunchOut);
		write_record_to_log(chrono::UTC::now(), Action::PunchIn);
	}
	else if args.is_present("out") {
		ensure_last_record_is_of_action(Action::PunchIn);
		write_record_to_log(chrono::UTC::now(), Action::PunchOut);
	}
	else if args.is_present("card") {
		print_last_record();
	}
}

fn ensure_last_record_is_of_action(expected_action: Action) {

	let mut config_file = get_conf_file(true, false).unwrap();
    let mut record = empty_record();

    match populate_record_at_offset_from_end(&mut config_file, &mut record, 0) {
    	Ok(_) => {},
    	Err(e) => {
    		println!("Couldn't create punch log: {}.\nExiting.", e);
			process::exit(1)
    	}
    }

    if record.action != expected_action {
    	match expected_action {
    		Action::PunchIn => {
    			println!("Already punched out, punch in first!");
				process::exit(1)
    		}
    		Action::PunchOut => {
    			println!("Already punched in, punch out first!");
    			process::exit(1)
    		}
    		Action::Unset => {
    			println!("Found unset action, log file corrupt");
    			process::exit(1)
    		}
    	}

    }
}

fn get_conf_file(read: bool, append: bool) -> io::Result<File> {

	let mut conf_file = PathBuf::new();
    conf_file.push(env::home_dir().unwrap());
    conf_file.push(".punch");
    conf_file.push("punch.log");

    OpenOptions::new().read(read).append(append).open(conf_file)
}

fn empty_record() -> Record {
	Record {
    	action: Action::Unset,
    	timestamp: chrono::UTC::now()
    }
}

fn print_last_record() {
    let mut config_file = get_conf_file(true, false).unwrap();
    let mut record = empty_record();

    match populate_record_at_offset_from_end(&mut config_file, &mut record, 0) {
    	Ok(_) => {},
    	Err(e) => {
    		println!("Couldn't create punch log: {}.\nExiting.", e);
			process::exit(1)
    	}
    }

    if record.action == Action::PunchIn {
    	let current_timestamp = chrono::UTC::now();
    	let time_punched_in = current_timestamp.sub(record.timestamp);
    	println!("Punched in since {} ({})", record.timestamp, time_punched_in)
    }
    else {
    	let mut previous_record = empty_record();
    	match populate_record_at_offset_from_end(&mut config_file, &mut previous_record, 1) {
	    	Ok(_) => {},
	    	Err(e) => {
	    		println!("Couldn't create punch log: {}.\nExiting.", e);
				process::exit(1)
	    	}
	    }

    	let delta = record.timestamp.sub(previous_record.timestamp);
    	println!("Previously punched in between {} and {} ({})",
    		previous_record.timestamp, record.timestamp, delta)
    }
}

fn populate_record_at_offset_from_end(config_file: &mut File, record: &mut Record, offset_from_end: u64) -> Result<(), String> {
	seek_to_record_offset(config_file, offset_from_end);
	populate_record_at_current_offset(config_file, record);
	Ok(())
}

fn write_record_to_log(tm: DateTime<UTC>, action: Action) {
	let action_token = match action {
		Action::PunchIn => "I",
		Action::PunchOut => "O",
		Action::Unset => "U"
	};

    let mut config_file = get_conf_file(false, true).unwrap();
    let fmt = tm.format("%FT%T");
	let formatted_timestamp = fmt.to_string();
	do_file_write(formatted_timestamp.as_bytes(), &mut config_file);
	do_file_write("_".as_bytes(), &mut config_file);
	do_file_write(action_token.as_bytes(), &mut config_file);
	do_file_write("\n".as_bytes(), &mut config_file);
}

fn populate_record_at_current_offset(f: &mut File, record: &mut Record) -> bool {
	let mut data = [0 as u8; RECORD_LENGTH];
	let read = f.read(&mut data);
	if read.unwrap() != RECORD_LENGTH {
		panic!("Could not read complete record")
	}
	let (ts_data, rest) = data.split_at(19);
	let timestamp = str::from_utf8(&ts_data).unwrap();
	let parse_result = chrono::UTC.datetime_from_str(&timestamp, "%FT%T");

	let record_ts = parse_result.
		unwrap().with_timezone(&chrono::UTC);
	record.timestamp = record_ts;
	let action_string = str::from_utf8(&rest).unwrap();
	if action_string == "_O\n" {
		record.action = Action::PunchOut;
	}
	else if action_string == "_I\n" {
		record.action = Action::PunchIn;
	}
	else {
		panic!("Could not determine action type from '{}'", action_string)
	}
	return true
}

fn seek_to_record_offset(f: &mut File, record_offset: u64) {
	let m = f.metadata().unwrap();
	let file_len = m.len();

	let record_length_in_bytes = RECORD_LENGTH as u64;
	let seek_offset = file_len - ((record_offset + 1) * record_length_in_bytes);

	if f.seek(SeekFrom::Start(seek_offset)).unwrap() != seek_offset {
		panic!("Could not seek to record offset {}", record_offset)
	}
}

fn do_file_write(data: &[u8], f: &mut File) {
	match f.write_all(data) {
    	Ok(_) => {},
    	Err(e) => println!("Failed to write data to log: {}", e)
    }
}

fn ensure_log_file_exists() -> io::Result<()> {
    let mut conf_dir = PathBuf::new();
    conf_dir.push(env::home_dir().unwrap());
    conf_dir.push(".punch");
    let config_path = conf_dir.as_path();

    let mut conf_file_builder = PathBuf::from(config_path);
    conf_file_builder.push("punch.log");

    let mut dir_builder = DirBuilder::new();
    dir_builder.recursive(true);

    try!(dir_builder.create(config_path));

    let conf_file = conf_file_builder.as_path();
    match OpenOptions::new().create(true).write(true).open(conf_file) {
    	Ok(_) => Ok(()),
    	Err(e) => Err(e)
    }
}<|endoftext|>


<commit_before>extern crate rand;
extern crate hyper;

use std::fs::{File, OpenOptions, remove_file};
use std::str::FromStr;
use std::path::Path;

mod pasteid;
use pasteid::PasteID;

use std::io;
use hyper::header::{ContentLength, ContentType};
use hyper::server::{Server, Request, Response};
use hyper::status::StatusCode;
use hyper::uri::RequestUri::*;

const ID_SIZE: usize = 8;
const USAGE: &'static [u8] = b"
pastabin 0.0.1 - Minimal pastebin clone in Rust. Manual post required. CLI recommended.

    USAGE

      POST /

        accepts raw data in the body of the request and responds with a URL of
        a page containing the body's content

      GET /<id>

        retrieves the content for the paste with id `<id>`

    EXAMPLE

        Upload a file:

            curl --data-binary @file.txt https://pasta.lol/

        Upload from stdin:

            echo \"Hellow, World\" | curl --data-binary @- https://pasta.lol/

        Delete an existing paste:

            curl -X DELETE https://pasta.lol/<id>

    SOURCE CODE

        https://github.com/nopjmp/pastabin

    LICENSE

        MIT License. https://github.com/nopjmp/pastabin/blob/master/LICENSE.md
    ";

fn retrieve_paste(id: PasteID) -> Option<File> {
    File::open(&id.filename()).ok()
}

fn create_paste(id: &PasteID) -> io::Result<File> {
    OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(&id.filename())
}

macro_rules! try_handle {
    ($res:ident, $e:expr, $statuscode:expr) => {{
        match $e.ok() {
            Some(v) => v,
            None => {
                *$res.status_mut() = $statuscode;
                return;
            },
        }
    }}
}

fn handle(mut req: Request, mut res: Response) {
    match req.method {
        hyper::Get => {
            match req.uri.clone() {
                AbsolutePath(path) => {
                    if path == "/" {
                        res.headers_mut().set(ContentType::plaintext());
                        res.send(USAGE).unwrap();
                    } else if path == "/favicon.ico" {
                        // todo favicon
                        *res.status_mut() = StatusCode::NotFound;
                    } else if let Ok(id) = PasteID::from_str(path.trim_left_matches("/")) {
                        match retrieve_paste(id) {
                            Some(mut file) => {
                                let metadata = try_handle!(res,
                                                           file.metadata(),
                                                           StatusCode::InternalServerError);
                                res.headers_mut().set(ContentLength(metadata.len()));
                                res.headers_mut().set(ContentType::plaintext());
                                io::copy(&mut file, &mut res.start().unwrap()).unwrap();
                            }
                            None => *res.status_mut() = StatusCode::NotFound,
                        }
                    } else {
                        *res.status_mut() = StatusCode::BadRequest;
                    }
                }
                _ => *res.status_mut() = StatusCode::BadRequest,
            }
        }
        hyper::Post => {
            match req.uri.clone() {
                AbsolutePath(path) => {
                    if path != "/" {
                        *res.status_mut() = StatusCode::BadRequest;
                    } else {
                        let mut tries = 0;
                        let mut id = PasteID::new(ID_SIZE);
                        let mut file = create_paste(&id);
                        while file.is_err() && tries < 3 {
                            id = PasteID::new(ID_SIZE);
                            file = create_paste(&id);
                            tries += 1;
                        }
                        if file.is_err() {
                            *res.status_mut() = StatusCode::InternalServerError;
                        } else {
                            try_handle!(res,
                                        io::copy(&mut req,
                                                 &mut try_handle!(res,
                                                                  file,
                                                                  StatusCode::InternalServerError)),
                                        StatusCode::InternalServerError);
                            *res.status_mut() = StatusCode::Created;
                            res.send(format!("https://pasta.lol/{}\n", id).as_bytes())
                                .unwrap();
                        }
                    }
                }
                _ => *res.status_mut() = StatusCode::BadRequest,
            }
        }
        hyper::Delete => {
            match req.uri.clone() {
                AbsolutePath(path) => {
                    let id = try_handle!(res,
                                         PasteID::from_str(path.trim_left_matches("/")),
                                         StatusCode::BadRequest);
                    let filename = id.filename();
                    let path = Path::new(&filename);
                    if path.exists() {
                        try_handle!(res, remove_file(path), StatusCode::InternalServerError);
                    } else {
                        *res.status_mut() = StatusCode::NotFound;
                    }
                }
                _ => *res.status_mut() = StatusCode::BadRequest,
            }
        }
        _ => *res.status_mut() = StatusCode::MethodNotAllowed,
    }
}

fn main() {
    let mut ipv4 = Server::http("127.0.0.1:8080").unwrap();
    ipv4.keep_alive(None);
    let _guardipv4 = ipv4.handle(handle);
}
<commit_msg>fix variable names from standalone experiment<commit_after>extern crate rand;
extern crate hyper;

use std::fs::{File, OpenOptions, remove_file};
use std::str::FromStr;
use std::path::Path;

mod pasteid;
use pasteid::PasteID;

use std::io;
use hyper::header::{ContentLength, ContentType};
use hyper::server::{Server, Request, Response};
use hyper::status::StatusCode;
use hyper::uri::RequestUri::*;

const ID_SIZE: usize = 8;
const USAGE: &'static [u8] = b"
pastabin 0.0.1 - Minimal pastebin clone in Rust. Manual post required. CLI recommended.

    USAGE

      POST /

        accepts raw data in the body of the request and responds with a URL of
        a page containing the body's content

      GET /<id>

        retrieves the content for the paste with id `<id>`

    EXAMPLE

        Upload a file:

            curl --data-binary @file.txt https://pasta.lol/

        Upload from stdin:

            echo \"Hellow, World\" | curl --data-binary @- https://pasta.lol/

        Delete an existing paste:

            curl -X DELETE https://pasta.lol/<id>

    SOURCE CODE

        https://github.com/nopjmp/pastabin

    LICENSE

        MIT License. https://github.com/nopjmp/pastabin/blob/master/LICENSE.md
    ";

fn retrieve_paste(id: PasteID) -> Option<File> {
    File::open(&id.filename()).ok()
}

fn create_paste(id: &PasteID) -> io::Result<File> {
    OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(&id.filename())
}

macro_rules! try_handle {
    ($res:ident, $e:expr, $statuscode:expr) => {{
        match $e.ok() {
            Some(v) => v,
            None => {
                *$res.status_mut() = $statuscode;
                return;
            },
        }
    }}
}

fn handle(mut req: Request, mut res: Response) {
    match req.method {
        hyper::Get => {
            match req.uri.clone() {
                AbsolutePath(path) => {
                    if path == "/" {
                        res.headers_mut().set(ContentType::plaintext());
                        res.send(USAGE).unwrap();
                    } else if path == "/favicon.ico" {
                        // todo favicon
                        *res.status_mut() = StatusCode::NotFound;
                    } else if let Ok(id) = PasteID::from_str(path.trim_left_matches("/")) {
                        match retrieve_paste(id) {
                            Some(mut file) => {
                                let metadata = try_handle!(res,
                                                           file.metadata(),
                                                           StatusCode::InternalServerError);
                                res.headers_mut().set(ContentLength(metadata.len()));
                                res.headers_mut().set(ContentType::plaintext());
                                io::copy(&mut file, &mut res.start().unwrap()).unwrap();
                            }
                            None => *res.status_mut() = StatusCode::NotFound,
                        }
                    } else {
                        *res.status_mut() = StatusCode::BadRequest;
                    }
                }
                _ => *res.status_mut() = StatusCode::BadRequest,
            }
        }
        hyper::Post => {
            match req.uri.clone() {
                AbsolutePath(path) => {
                    if path != "/" {
                        *res.status_mut() = StatusCode::BadRequest;
                    } else {
                        let mut tries = 0;
                        let mut id = PasteID::new(ID_SIZE);
                        let mut file = create_paste(&id);
                        while file.is_err() && tries < 3 {
                            id = PasteID::new(ID_SIZE);
                            file = create_paste(&id);
                            tries += 1;
                        }
                        if file.is_err() {
                            *res.status_mut() = StatusCode::InternalServerError;
                        } else {
                            try_handle!(res,
                                        io::copy(&mut req,
                                                 &mut try_handle!(res,
                                                                  file,
                                                                  StatusCode::InternalServerError)),
                                        StatusCode::InternalServerError);
                            *res.status_mut() = StatusCode::Created;
                            res.send(format!("https://pasta.lol/{}\n", id).as_bytes())
                                .unwrap();
                        }
                    }
                }
                _ => *res.status_mut() = StatusCode::BadRequest,
            }
        }
        hyper::Delete => {
            match req.uri.clone() {
                AbsolutePath(path) => {
                    let id = try_handle!(res,
                                         PasteID::from_str(path.trim_left_matches("/")),
                                         StatusCode::BadRequest);
                    let filename = id.filename();
                    let path = Path::new(&filename);
                    if path.exists() {
                        try_handle!(res, remove_file(path), StatusCode::InternalServerError);
                    } else {
                        *res.status_mut() = StatusCode::NotFound;
                    }
                }
                _ => *res.status_mut() = StatusCode::BadRequest,
            }
        }
        _ => *res.status_mut() = StatusCode::MethodNotAllowed,
    }
}

fn main() {
    let mut server = Server::http("127.0.0.1:8080").unwrap();
    server.keep_alive(None);
    let _guard = server.handle(handle);
}
<|endoftext|>