<commit_before>#![allow(unused_variables)]

extern crate glutin_window;
extern crate graphics;
extern crate rebind;
extern crate piston;
extern crate opengl_graphics;
extern crate viewport;

use glutin_window::GlutinWindow;
use graphics::*;
use opengl_graphics::{GlGraphics, OpenGL};
use piston::event_loop::{EventMap, Events};
use piston::input::{
    Event,
    Input,
    Motion,
    RenderArgs,
    RenderEvent,
    UpdateArgs,
    UpdateEvent
};
use piston::input::keyboard::Key;
use piston::input::Button::Keyboard;
use piston::window::{Window, WindowSettings};
use rebind::{Action, InputTranslator, RebindBuilder, Translated};
use std::cell::RefCell;
use std::rc::Rc;

type RcWindow = Rc<RefCell<GlutinWindow>>;
type RcGraphics = Rc<RefCell<GlGraphics>>;
type RgbaColor = [f32; 4];

const RED: RgbaColor = [1.0, 0.0, 0.0, 1.0];
const GREEN: RgbaColor = [0.0, 1.0, 0.0, 1.0];
const BLACK: RgbaColor = [0.0, 0.0, 0.0, 1.0];

struct App {
    window: RcWindow,
    graphics: RcGraphics,
    translator: InputTranslator<CharacterAction>,
    character: Character,
    cursor: VirtualCursor,
    bg_color: RgbaColor
}

impl App {
    fn input(&mut self, input: &Input) {
        if let Some(t) = self.translator.translate(input) {
            match t {
                Translated::Press(action) => {
                    const CHARACTER_WALK_SPEED_INCREMENT: f64 = 400.0;
                    match action {
                        CharacterAction::Jump => {
                            println!("You jumped! Yay!");
                        },
                        CharacterAction::MoveLeft => {
                            if self.character.current_velocity[0] > (self.character.max_velocity[0] * -1.0) {
                                self.character.current_velocity[0] -= CHARACTER_WALK_SPEED_INCREMENT;
                            }
                        },
                        CharacterAction::MoveRight => {
                            if self.character.current_velocity[0] < self.character.max_velocity[0] {
                                self.character.current_velocity[0] += CHARACTER_WALK_SPEED_INCREMENT;
                            }
                        }
                    }
                },
                Translated::Release(_) => {
                    self.character.current_velocity = [0.0, 0.0];
                },
                Translated::Move(Motion::MouseCursor(x, y)) => {
                    self.cursor.position = [x, y];
                },
                _ => { }
            }
        }
    }

    fn update(&mut self, args: &UpdateArgs, window: RcWindow) {
        // we need to pass the window to update (and set the size here) because using
        // the update event from the window events queue is currently broken.
        self.translator.set_size(window.borrow().size());

        // update the character's velocity
        let ctl = self.character.topleft;
        let v = self.character.current_velocity;

        self.character.topleft = [ctl[0] + (v[0] * args.dt), ctl[1] + (v[1] * args.dt)];
    }

    fn render(&mut self, args: &RenderArgs) {
        let mut gl_graphics = self.graphics.borrow_mut();

        // draw the background color
        {
            gl_graphics.draw(args.viewport(), |_, gl| clear(self.bg_color, gl));
        }

        // draw the character
        {
            let square = rectangle::square(self.character.topleft[0],
                                           self.character.topleft[1],
                                           self.character.size);

            gl_graphics.draw(args.viewport(), |c, gl| rectangle(self.character.color, square, c.transform, gl));
        }

        // draw the cursor dot
        {
            let dot = ellipse::circle(self.cursor.position[0],
                                      self.cursor.position[1],
                                      self.cursor.size);
            gl_graphics.draw(args.viewport(), |c, gl| ellipse(self.cursor.color, dot, c.transform, gl));
        }
    }
}

struct Character {
    color: RgbaColor,
    topleft: [f64; 2],
    current_velocity: [f64; 2],
    max_velocity: [f64; 2],
    size: f64
}

impl Character {
    fn new(col: [f32; 4], tl: [f64; 2], sz: f64) -> Self {
        Character {
            color: col,
            topleft: tl,
            current_velocity: [0.0, 0.0],
            max_velocity: [800.0, 0.0],
            size: sz
        }
    }
}

struct VirtualCursor {
    position: [f64; 2],
    color: RgbaColor,
    size: f64
}

impl VirtualCursor {
    fn new() -> Self {
        VirtualCursor {
            position: [0.0, 0.0],
            color: GREEN,
            size: 5.0
        }
    }
}

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
enum CharacterAction {
    Jump,
    MoveLeft,
    MoveRight
}

impl Action for CharacterAction { }

fn main() {
    const OPENGL: OpenGL = OpenGL::V3_2;
    const WINDOW_SIZE: (u32, u32) = (800, 600);

    let window = WindowSettings::new("calaxite", WINDOW_SIZE)
        .exit_on_esc(true)
        .fullscreen(false)
        .opengl(OPENGL)
        .vsync(true)
        .build()
        .unwrap_or_else(|e| panic!("Could not create window: {}", e));

    let gl_graphics = GlGraphics::new(OPENGL);

    let translator = RebindBuilder::new(WINDOW_SIZE)
        .with_action_mapping(Keyboard(Key::Space), CharacterAction::Jump)
        .with_action_mapping(Keyboard(Key::Left),  CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::A),     CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::Right), CharacterAction::MoveRight)
        .with_action_mapping(Keyboard(Key::D),     CharacterAction::MoveRight)
        .y_motion_inverted(true)
        .build_translator();

    let character = Character::new(RED, [30.0, (WINDOW_SIZE.1 as f64) * 0.85], 50.0);

    let mut app = App {
        window: Rc::new(RefCell::new(window)),
        graphics: Rc::new(RefCell::new(gl_graphics)),
        translator: translator,
        character: character,
        cursor: VirtualCursor::new(),
        bg_color: BLACK
    };

    for e in  app.window.clone().events() {
        let app_window = app.window.clone();
        match e {
            Event::Render(r) => { app.render(&r); },
            Event::Update(u) => { app.update(&u, app_window); },
            Event::Input(i) => { app.input(&i); },
            _ => { }
        }
    }
}
<commit_msg>Remove accidentally added testing code from previous commit<commit_after>#![allow(unused_variables)]

extern crate glutin_window;
extern crate graphics;
extern crate rebind;
extern crate piston;
extern crate opengl_graphics;
extern crate viewport;

use glutin_window::GlutinWindow;
use graphics::*;
use opengl_graphics::{GlGraphics, OpenGL};
use piston::event_loop::{EventMap, Events};
use piston::input::{
    Event,
    Input,
    Motion,
    RenderArgs,
    RenderEvent,
    UpdateArgs,
    UpdateEvent
};
use piston::input::keyboard::Key;
use piston::input::Button::Keyboard;
use piston::window::{Window, WindowSettings};
use rebind::{Action, InputTranslator, RebindBuilder, Translated};
use std::cell::RefCell;
use std::rc::Rc;

type RcWindow = Rc<RefCell<GlutinWindow>>;
type RcGraphics = Rc<RefCell<GlGraphics>>;
type RgbaColor = [f32; 4];

const RED: RgbaColor = [1.0, 0.0, 0.0, 1.0];
const GREEN: RgbaColor = [0.0, 1.0, 0.0, 1.0];
const BLACK: RgbaColor = [0.0, 0.0, 0.0, 1.0];

struct App {
    window: RcWindow,
    graphics: RcGraphics,
    translator: InputTranslator<CharacterAction>,
    character: Character,
    cursor: VirtualCursor,
    bg_color: RgbaColor
}

impl App {
    fn input(&mut self, input: &Input) {
        if let Some(t) = self.translator.translate(input) {
            match t {
                Translated::Press(action) => {
                    const CHARACTER_WALK_SPEED_INCREMENT: f64 = 400.0;
                    match action {
                        CharacterAction::Jump => {
                            println!("You jumped! Yay!");
                        },
                        CharacterAction::MoveLeft => {
                            if self.character.current_velocity[0] > (self.character.max_velocity[0] * -1.0) {
                                self.character.current_velocity[0] -= CHARACTER_WALK_SPEED_INCREMENT;
                            }
                        },
                        CharacterAction::MoveRight => {
                            if self.character.current_velocity[0] < self.character.max_velocity[0] {
                                self.character.current_velocity[0] += CHARACTER_WALK_SPEED_INCREMENT;
                            }
                        }
                    }
                },
                Translated::Release(_) => {
                    self.character.current_velocity = [0.0, 0.0];
                },
                Translated::Move(Motion::MouseCursor(x, y)) => {
                    self.cursor.position = [x, y];
                },
                _ => { }
            }
        }
    }

    fn update(&mut self, args: &UpdateArgs, window: RcWindow) {
        // we need to pass the window to update (and set the size here) because using
        // the update event from the window events queue is currently broken.
        self.translator.set_size(window.borrow().size());

        // update the character's velocity
        let ctl = self.character.topleft;
        let v = self.character.current_velocity;

        self.character.topleft = [ctl[0] + (v[0] * args.dt), ctl[1] + (v[1] * args.dt)];
    }

    fn render(&mut self, args: &RenderArgs) {
        let mut gl_graphics = self.graphics.borrow_mut();

        // draw the background color
        {
            gl_graphics.draw(args.viewport(), |_, gl| clear(self.bg_color, gl));
        }

        // draw the character
        {
            let square = rectangle::square(self.character.topleft[0],
                                           self.character.topleft[1],
                                           self.character.size);

            gl_graphics.draw(args.viewport(), |c, gl| rectangle(self.character.color, square, c.transform, gl));
        }

        // draw the cursor dot
        {
            let dot = ellipse::circle(self.cursor.position[0],
                                      self.cursor.position[1],
                                      self.cursor.size);
            gl_graphics.draw(args.viewport(), |c, gl| ellipse(self.cursor.color, dot, c.transform, gl));
        }
    }
}

struct Character {
    color: RgbaColor,
    topleft: [f64; 2],
    current_velocity: [f64; 2],
    max_velocity: [f64; 2],
    size: f64
}

impl Character {
    fn new(col: [f32; 4], tl: [f64; 2], sz: f64) -> Self {
        Character {
            color: col,
            topleft: tl,
            current_velocity: [0.0, 0.0],
            max_velocity: [800.0, 0.0],
            size: sz
        }
    }
}

struct VirtualCursor {
    position: [f64; 2],
    color: RgbaColor,
    size: f64
}

impl VirtualCursor {
    fn new() -> Self {
        VirtualCursor {
            position: [0.0, 0.0],
            color: GREEN,
            size: 5.0
        }
    }
}

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
enum CharacterAction {
    Jump,
    MoveLeft,
    MoveRight
}

impl Action for CharacterAction { }

fn main() {
    const OPENGL: OpenGL = OpenGL::V3_2;
    const WINDOW_SIZE: (u32, u32) = (800, 600);

    let window = WindowSettings::new("calaxite", WINDOW_SIZE)
        .exit_on_esc(true)
        .fullscreen(false)
        .opengl(OPENGL)
        .vsync(true)
        .build()
        .unwrap_or_else(|e| panic!("Could not create window: {}", e));

    let gl_graphics = GlGraphics::new(OPENGL);

    let translator = RebindBuilder::new(WINDOW_SIZE)
        .with_action_mapping(Keyboard(Key::Space), CharacterAction::Jump)
        .with_action_mapping(Keyboard(Key::Left),  CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::A),     CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::Right), CharacterAction::MoveRight)
        .with_action_mapping(Keyboard(Key::D),     CharacterAction::MoveRight)
        .build_translator();

    let character = Character::new(RED, [30.0, (WINDOW_SIZE.1 as f64) * 0.85], 50.0);

    let mut app = App {
        window: Rc::new(RefCell::new(window)),
        graphics: Rc::new(RefCell::new(gl_graphics)),
        translator: translator,
        character: character,
        cursor: VirtualCursor::new(),
        bg_color: BLACK
    };

    for e in  app.window.clone().events() {
        let app_window = app.window.clone();
        match e {
            Event::Render(r) => { app.render(&r); },
            Event::Update(u) => { app.update(&u, app_window); },
            Event::Input(i) => { app.input(&i); },
            _ => { }
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::fmt::Display;

use ::{ROUTE_STRUCT_PREFIX, ROUTE_FN_PREFIX, PARAM_PREFIX};
use utils::{emit_item, span, sep_by_tok, option_as_expr, strip_ty_lifetimes};
use utils::{SpanExt, IdentExt, ArgExt};
use parser::{Param, RouteParams};

use syntax::codemap::{Span, Spanned};
use syntax::tokenstream::TokenTree;
use syntax::ast::{Arg, Ident, Stmt, Expr, MetaItem, Path};
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::ptr::P;

use rocket::http::{Method, ContentType};

fn method_to_path(ecx: &ExtCtxt, method: Method) -> Path {
    quote_enum!(ecx, method => ::rocket::http::Method {
        Options, Get, Post, Put, Delete, Head, Trace, Connect, Patch;
    })
}

fn content_type_to_expr(ecx: &ExtCtxt, ct: Option<ContentType>) -> Option<P<Expr>> {
    ct.map(|ct| {
        let (top, sub) = (ct.ttype.as_str(), ct.subtype.as_str());
        quote_expr!(ecx, ::rocket::http::ContentType {
            ttype: ::rocket::http::ascii::UncasedAscii {
                string: ::std::borrow::Cow::Borrowed($top)
            },
            subtype: ::rocket::http::ascii::UncasedAscii {
                string: ::std::borrow::Cow::Borrowed($sub)
            },
            params: None
        })
    })
}

trait RouteGenerateExt {
    fn gen_form(&self, &ExtCtxt, Option<&Spanned<Ident>>, P<Expr>) -> Option<Stmt>;
    fn missing_declared_err<T: Display>(&self, ecx: &ExtCtxt, arg: &Spanned<T>);

    fn generate_data_statement(&self, ecx: &ExtCtxt) -> Option<Stmt>;
    fn generate_query_statement(&self, ecx: &ExtCtxt) -> Option<Stmt>;
    fn generate_param_statements(&self, ecx: &ExtCtxt) -> Vec<Stmt>;
    fn generate_fn_arguments(&self, ecx: &ExtCtxt) -> Vec<TokenTree>;
    fn explode(&self, ecx: &ExtCtxt) -> (&String, Path, P<Expr>, P<Expr>);
}

impl RouteGenerateExt for RouteParams {
    fn missing_declared_err<T: Display>(&self, ecx: &ExtCtxt, arg: &Spanned<T>) {
        let fn_span = self.annotated_fn.span();
        let msg = format!("'{}' is declared as an argument...", arg.node);
        ecx.span_err(arg.span, &msg);
        ecx.span_err(fn_span, "...but isn't in the function signature.");
    }

    fn gen_form(&self, ecx: &ExtCtxt, param: Option<&Spanned<Ident>>,
                form_string: P<Expr>) -> Option<Stmt> {
        let arg = param.and_then(|p| self.annotated_fn.find_input(&p.node.name));
        if param.is_none() {
            return None;
        } else if arg.is_none() {
            self.missing_declared_err(ecx, param.unwrap());
            return None;
        }

        let arg = arg.unwrap();
        let name = arg.ident().expect("form param identifier").prepend(PARAM_PREFIX);
        let ty = strip_ty_lifetimes(arg.ty.clone());
        Some(quote_stmt!(ecx,
            let $name: $ty =
                match ::rocket::request::FromForm::from_form_string($form_string) {
                    Ok(v) => v,
                    Err(_) => return ::rocket::Outcome::Forward(_data)
                };
        ).expect("form statement"))
    }

    fn generate_data_statement(&self, ecx: &ExtCtxt) -> Option<Stmt> {
        let param = self.data_param.as_ref().map(|p| &p.value);
        let arg = param.and_then(|p| self.annotated_fn.find_input(&p.node.name));
        if param.is_none() {
            return None;
        } else if arg.is_none() {
            self.missing_declared_err(ecx, param.unwrap());
            return None;
        }

        let arg = arg.unwrap();
        let name = arg.ident().expect("form param identifier").prepend(PARAM_PREFIX);
        let ty = strip_ty_lifetimes(arg.ty.clone());
        Some(quote_stmt!(ecx,
            let $name: $ty =
                match ::rocket::data::FromData::from_data(&_req, _data) {
                    ::rocket::Outcome::Success(d) => d,
                    ::rocket::Outcome::Forward(d) =>
                        return ::rocket::Outcome::Forward(d),
                    ::rocket::Outcome::Failure((code, _)) => {
                        return ::rocket::Outcome::Failure(code);
                    }
                };
        ).expect("data statement"))
    }

    fn generate_query_statement(&self, ecx: &ExtCtxt) -> Option<Stmt> {
        let param = self.query_param.as_ref();
        let expr = quote_expr!(ecx,
           match _req.uri().query() {
               Some(query) => query,
               None => return ::rocket::Outcome::Forward(_data)
           }
        );

        self.gen_form(ecx, param, expr)
    }

    // TODO: Add some kind of logging facility in Rocket to get be able to log
    // an error/debug message if parsing a parameter fails.
    fn generate_param_statements(&self, ecx: &ExtCtxt) -> Vec<Stmt> {
        let mut fn_param_statements = vec![];

        // Generate a statement for every declared paramter in the path.
        let mut declared_set = HashSet::new();
        for (i, param) in self.path_params(ecx).enumerate() {
            declared_set.insert(param.ident().name);
            let ty = match self.annotated_fn.find_input(&param.ident().name) {
                Some(arg) => strip_ty_lifetimes(arg.ty.clone()),
                None => {
                    self.missing_declared_err(ecx, param.inner());
                    continue;
                }
            };

            // Note: the `None` case shouldn't happen if a route is matched.
            let ident = param.ident().prepend(PARAM_PREFIX);
            let expr = match param {
                Param::Single(_) => quote_expr!(ecx, match _req.get_param_str($i) {
                    Some(s) => <$ty as ::rocket::request::FromParam>::from_param(s),
                    None => return ::rocket::Outcome::Forward(_data)
                }),
                Param::Many(_) => quote_expr!(ecx, match _req.get_raw_segments($i) {
                    Some(s) => <$ty as ::rocket::request::FromSegments>::from_segments(s),
                    None => return ::rocket::Outcome::Forward(_data)
                }),
            };

            let original_ident = param.ident();
            fn_param_statements.push(quote_stmt!(ecx,
                let $ident: $ty = match $expr {
                    Ok(v) => v,
                    Err(e) => {
                        println!("    => Failed to parse '{}': {:?}",
                                 stringify!($original_ident), e);
                        return ::rocket::Outcome::Forward(_data)
                    }
                };
            ).expect("declared param parsing statement"));
        }

        // A from_request parameter is one that isn't declared, data, or query.
        let from_request = |a: &&Arg| {
            if let Some(name) = a.name() {
                !declared_set.contains(name)
                    && self.data_param.as_ref().map_or(true, |p| {
                        !a.named(&p.value().name)
                    }) && self.query_param.as_ref().map_or(true, |p| {
                        !a.named(&p.node.name)
                    })
            } else {
                ecx.span_err(a.pat.span, "argument names must be identifiers");
                false
            }
        };

        // Generate the code for `from_request` parameters.
        let all = &self.annotated_fn.decl().inputs;
        for arg in all.iter().filter(from_request) {
            let ident = arg.ident().unwrap().prepend(PARAM_PREFIX);
            let ty = strip_ty_lifetimes(arg.ty.clone());
            fn_param_statements.push(quote_stmt!(ecx,
                let $ident: $ty = match
                        ::rocket::request::FromRequest::from_request(&_req) {
                    ::rocket::outcome::Outcome::Success(v) => v,
                    ::rocket::outcome::Outcome::Forward(_) =>
                        return ::rocket::Outcome::forward(_data),
                    ::rocket::outcome::Outcome::Failure((code, _)) => {
                        return ::rocket::Outcome::Failure(code)
                    },
                };
            ).expect("undeclared param parsing statement"));
        }

        fn_param_statements
    }

    fn generate_fn_arguments(&self, ecx: &ExtCtxt) -> Vec<TokenTree> {
        let args = self.annotated_fn.decl().inputs.iter()
            .filter_map(|a| a.ident())
            .map(|ident| ident.prepend(PARAM_PREFIX))
            .collect::<Vec<Ident>>();

        sep_by_tok(ecx, &args, token::Comma)
    }

    fn explode(&self, ecx: &ExtCtxt) -> (&String, Path, P<Expr>, P<Expr>) {
        let path = &self.path.node;
        let method = method_to_path(ecx, self.method.node);
        let format = self.format.as_ref().map(|kv| kv.value().clone());
        let content_type = option_as_expr(ecx, &content_type_to_expr(ecx, format));
        let rank = option_as_expr(ecx, &self.rank);

        (path, method, content_type, rank)
    }
}

// FIXME: Compilation fails when parameters have the same name as the function!
fn generic_route_decorator(known_method: Option<Spanned<Method>>,
                           ecx: &mut ExtCtxt,
                           sp: Span,
                           meta_item: &MetaItem,
                           annotated: &Annotatable,
                           push: &mut FnMut(Annotatable)) {
    // Parse the route and generate the code to create the form and param vars.
    let route = RouteParams::from(ecx, sp, known_method, meta_item, annotated);
    debug!("Route params: {:?}", route);

    let param_statements = route.generate_param_statements(ecx);
    let query_statement = route.generate_query_statement(ecx);
    let data_statement = route.generate_data_statement(ecx);
    let fn_arguments = route.generate_fn_arguments(ecx);

    // Generate and emit the wrapping function with the Rocket handler signature.
    let user_fn_name = route.annotated_fn.ident();
    let route_fn_name = user_fn_name.prepend(ROUTE_FN_PREFIX);
    emit_item(push, quote_item!(ecx,
         fn $route_fn_name<'_b>(_req: &'_b ::rocket::Request,  _data: ::rocket::Data)
                -> ::rocket::handler::Outcome<'_b> {
             $param_statements
             $query_statement
             $data_statement
             let responder = $user_fn_name($fn_arguments);
             ::rocket::handler::Outcome::of(responder)
         }
    ).unwrap());

    // Generate and emit the static route info that uses the just generated
    // function as its handler. A proper Rocket route will be created from this.
    let struct_name = user_fn_name.prepend(ROUTE_STRUCT_PREFIX);
    let (path, method, content_type, rank) = route.explode(ecx);
    emit_item(push, quote_item!(ecx,
        #[allow(non_upper_case_globals)]
        pub static $struct_name: ::rocket::StaticRouteInfo =
            ::rocket::StaticRouteInfo {
                method: $method,
                path: $path,
                handler: $route_fn_name,
                format: $content_type,
                rank: $rank,
            };
    ).unwrap());
}

pub fn route_decorator(ecx: &mut ExtCtxt,
                       sp: Span,
                       meta_item: &MetaItem,
                       annotated: &Annotatable,
                       push: &mut FnMut(Annotatable)) {
    generic_route_decorator(None, ecx, sp, meta_item, annotated, push);
}

macro_rules! method_decorator {
    ($name:ident, $method:ident) => (
        pub fn $name(ecx: &mut ExtCtxt, sp: Span, meta_item: &MetaItem,
                     annotated: &Annotatable, push: &mut FnMut(Annotatable)) {
            let i_sp = meta_item.span.shorten_to(stringify!($method).len());
            let method = Some(span(Method::$method, i_sp));
            generic_route_decorator(method, ecx, sp, meta_item, annotated, push);
        }
    )
}

method_decorator!(get_decorator, Get);
method_decorator!(put_decorator, Put);
method_decorator!(post_decorator, Post);
method_decorator!(delete_decorator, Delete);
method_decorator!(head_decorator, Head);
method_decorator!(patch_decorator, Patch);

// TODO: Allow this once Diesel incompatibility is fixed.
// method_decorator!(options_decorator, Options);
<commit_msg>Fix more codegen clippy warnings.<commit_after>use std::collections::HashSet;
use std::fmt::Display;

use ::{ROUTE_STRUCT_PREFIX, ROUTE_FN_PREFIX, PARAM_PREFIX};
use utils::{emit_item, span, sep_by_tok, option_as_expr, strip_ty_lifetimes};
use utils::{SpanExt, IdentExt, ArgExt};
use parser::{Param, RouteParams};

use syntax::codemap::{Span, Spanned};
use syntax::tokenstream::TokenTree;
use syntax::ast::{Arg, Ident, Stmt, Expr, MetaItem, Path};
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::ptr::P;

use rocket::http::{Method, ContentType};

fn method_to_path(ecx: &ExtCtxt, method: Method) -> Path {
    quote_enum!(ecx, method => ::rocket::http::Method {
        Options, Get, Post, Put, Delete, Head, Trace, Connect, Patch;
    })
}

fn content_type_to_expr(ecx: &ExtCtxt, ct: Option<ContentType>) -> Option<P<Expr>> {
    ct.map(|ct| {
        let (top, sub) = (ct.ttype.as_str(), ct.subtype.as_str());
        quote_expr!(ecx, ::rocket::http::ContentType {
            ttype: ::rocket::http::ascii::UncasedAscii {
                string: ::std::borrow::Cow::Borrowed($top)
            },
            subtype: ::rocket::http::ascii::UncasedAscii {
                string: ::std::borrow::Cow::Borrowed($sub)
            },
            params: None
        })
    })
}

trait RouteGenerateExt {
    fn gen_form(&self, &ExtCtxt, Option<&Spanned<Ident>>, P<Expr>) -> Option<Stmt>;
    fn missing_declared_err<T: Display>(&self, ecx: &ExtCtxt, arg: &Spanned<T>);

    fn generate_data_statement(&self, ecx: &ExtCtxt) -> Option<Stmt>;
    fn generate_query_statement(&self, ecx: &ExtCtxt) -> Option<Stmt>;
    fn generate_param_statements(&self, ecx: &ExtCtxt) -> Vec<Stmt>;
    fn generate_fn_arguments(&self, ecx: &ExtCtxt) -> Vec<TokenTree>;
    fn explode(&self, ecx: &ExtCtxt) -> (&String, Path, P<Expr>, P<Expr>);
}

impl RouteGenerateExt for RouteParams {
    fn missing_declared_err<T: Display>(&self, ecx: &ExtCtxt, arg: &Spanned<T>) {
        let fn_span = self.annotated_fn.span();
        let msg = format!("'{}' is declared as an argument...", arg.node);
        ecx.span_err(arg.span, &msg);
        ecx.span_err(fn_span, "...but isn't in the function signature.");
    }

    fn gen_form(&self, ecx: &ExtCtxt, param: Option<&Spanned<Ident>>,
                form_string: P<Expr>) -> Option<Stmt> {
        let arg = param.and_then(|p| self.annotated_fn.find_input(&p.node.name));
        if param.is_none() {
            return None;
        } else if arg.is_none() {
            self.missing_declared_err(ecx, param.unwrap());
            return None;
        }

        let arg = arg.unwrap();
        let name = arg.ident().expect("form param identifier").prepend(PARAM_PREFIX);
        let ty = strip_ty_lifetimes(arg.ty.clone());
        Some(quote_stmt!(ecx,
            let $name: $ty =
                match ::rocket::request::FromForm::from_form_string($form_string) {
                    Ok(v) => v,
                    Err(_) => return ::rocket::Outcome::Forward(_data)
                };
        ).expect("form statement"))
    }

    fn generate_data_statement(&self, ecx: &ExtCtxt) -> Option<Stmt> {
        let param = self.data_param.as_ref().map(|p| &p.value);
        let arg = param.and_then(|p| self.annotated_fn.find_input(&p.node.name));
        if param.is_none() {
            return None;
        } else if arg.is_none() {
            self.missing_declared_err(ecx, param.unwrap());
            return None;
        }

        let arg = arg.unwrap();
        let name = arg.ident().expect("form param identifier").prepend(PARAM_PREFIX);
        let ty = strip_ty_lifetimes(arg.ty.clone());
        Some(quote_stmt!(ecx,
            let $name: $ty =
                match ::rocket::data::FromData::from_data(_req, _data) {
                    ::rocket::Outcome::Success(d) => d,
                    ::rocket::Outcome::Forward(d) =>
                        return ::rocket::Outcome::Forward(d),
                    ::rocket::Outcome::Failure((code, _)) => {
                        return ::rocket::Outcome::Failure(code);
                    }
                };
        ).expect("data statement"))
    }

    fn generate_query_statement(&self, ecx: &ExtCtxt) -> Option<Stmt> {
        let param = self.query_param.as_ref();
        let expr = quote_expr!(ecx,
           match _req.uri().query() {
               Some(query) => query,
               None => return ::rocket::Outcome::Forward(_data)
           }
        );

        self.gen_form(ecx, param, expr)
    }

    // TODO: Add some kind of logging facility in Rocket to get be able to log
    // an error/debug message if parsing a parameter fails.
    fn generate_param_statements(&self, ecx: &ExtCtxt) -> Vec<Stmt> {
        let mut fn_param_statements = vec![];

        // Generate a statement for every declared paramter in the path.
        let mut declared_set = HashSet::new();
        for (i, param) in self.path_params(ecx).enumerate() {
            declared_set.insert(param.ident().name);
            let ty = match self.annotated_fn.find_input(&param.ident().name) {
                Some(arg) => strip_ty_lifetimes(arg.ty.clone()),
                None => {
                    self.missing_declared_err(ecx, param.inner());
                    continue;
                }
            };

            // Note: the `None` case shouldn't happen if a route is matched.
            let ident = param.ident().prepend(PARAM_PREFIX);
            let expr = match param {
                Param::Single(_) => quote_expr!(ecx, match _req.get_param_str($i) {
                    Some(s) => <$ty as ::rocket::request::FromParam>::from_param(s),
                    None => return ::rocket::Outcome::Forward(_data)
                }),
                Param::Many(_) => quote_expr!(ecx, match _req.get_raw_segments($i) {
                    Some(s) => <$ty as ::rocket::request::FromSegments>::from_segments(s),
                    None => return ::rocket::Outcome::Forward(_data)
                }),
            };

            let original_ident = param.ident();
            fn_param_statements.push(quote_stmt!(ecx,
                let $ident: $ty = match $expr {
                    Ok(v) => v,
                    Err(e) => {
                        println!("    => Failed to parse '{}': {:?}",
                                 stringify!($original_ident), e);
                        return ::rocket::Outcome::Forward(_data)
                    }
                };
            ).expect("declared param parsing statement"));
        }

        // A from_request parameter is one that isn't declared, data, or query.
        let from_request = |a: &&Arg| {
            if let Some(name) = a.name() {
                !declared_set.contains(name)
                    && self.data_param.as_ref().map_or(true, |p| {
                        !a.named(&p.value().name)
                    }) && self.query_param.as_ref().map_or(true, |p| {
                        !a.named(&p.node.name)
                    })
            } else {
                ecx.span_err(a.pat.span, "argument names must be identifiers");
                false
            }
        };

        // Generate the code for `from_request` parameters.
        let all = &self.annotated_fn.decl().inputs;
        for arg in all.iter().filter(from_request) {
            let ident = arg.ident().unwrap().prepend(PARAM_PREFIX);
            let ty = strip_ty_lifetimes(arg.ty.clone());
            fn_param_statements.push(quote_stmt!(ecx,
                let $ident: $ty = match
                        ::rocket::request::FromRequest::from_request(_req) {
                    ::rocket::outcome::Outcome::Success(v) => v,
                    ::rocket::outcome::Outcome::Forward(_) =>
                        return ::rocket::Outcome::forward(_data),
                    ::rocket::outcome::Outcome::Failure((code, _)) => {
                        return ::rocket::Outcome::Failure(code)
                    },
                };
            ).expect("undeclared param parsing statement"));
        }

        fn_param_statements
    }

    fn generate_fn_arguments(&self, ecx: &ExtCtxt) -> Vec<TokenTree> {
        let args = self.annotated_fn.decl().inputs.iter()
            .filter_map(|a| a.ident())
            .map(|ident| ident.prepend(PARAM_PREFIX))
            .collect::<Vec<Ident>>();

        sep_by_tok(ecx, &args, token::Comma)
    }

    fn explode(&self, ecx: &ExtCtxt) -> (&String, Path, P<Expr>, P<Expr>) {
        let path = &self.path.node;
        let method = method_to_path(ecx, self.method.node);
        let format = self.format.as_ref().map(|kv| kv.value().clone());
        let content_type = option_as_expr(ecx, &content_type_to_expr(ecx, format));
        let rank = option_as_expr(ecx, &self.rank);

        (path, method, content_type, rank)
    }
}

// FIXME: Compilation fails when parameters have the same name as the function!
fn generic_route_decorator(known_method: Option<Spanned<Method>>,
                           ecx: &mut ExtCtxt,
                           sp: Span,
                           meta_item: &MetaItem,
                           annotated: &Annotatable,
                           push: &mut FnMut(Annotatable)) {
    // Parse the route and generate the code to create the form and param vars.
    let route = RouteParams::from(ecx, sp, known_method, meta_item, annotated);
    debug!("Route params: {:?}", route);

    let param_statements = route.generate_param_statements(ecx);
    let query_statement = route.generate_query_statement(ecx);
    let data_statement = route.generate_data_statement(ecx);
    let fn_arguments = route.generate_fn_arguments(ecx);

    // Generate and emit the wrapping function with the Rocket handler signature.
    let user_fn_name = route.annotated_fn.ident();
    let route_fn_name = user_fn_name.prepend(ROUTE_FN_PREFIX);
    emit_item(push, quote_item!(ecx,
         fn $route_fn_name<'_b>(_req: &'_b ::rocket::Request,  _data: ::rocket::Data)
                -> ::rocket::handler::Outcome<'_b> {
             $param_statements
             $query_statement
             $data_statement
             let responder = $user_fn_name($fn_arguments);
             ::rocket::handler::Outcome::of(responder)
         }
    ).unwrap());

    // Generate and emit the static route info that uses the just generated
    // function as its handler. A proper Rocket route will be created from this.
    let struct_name = user_fn_name.prepend(ROUTE_STRUCT_PREFIX);
    let (path, method, content_type, rank) = route.explode(ecx);
    emit_item(push, quote_item!(ecx,
        #[allow(non_upper_case_globals)]
        pub static $struct_name: ::rocket::StaticRouteInfo =
            ::rocket::StaticRouteInfo {
                method: $method,
                path: $path,
                handler: $route_fn_name,
                format: $content_type,
                rank: $rank,
            };
    ).unwrap());
}

pub fn route_decorator(ecx: &mut ExtCtxt,
                       sp: Span,
                       meta_item: &MetaItem,
                       annotated: &Annotatable,
                       push: &mut FnMut(Annotatable)) {
    generic_route_decorator(None, ecx, sp, meta_item, annotated, push);
}

macro_rules! method_decorator {
    ($name:ident, $method:ident) => (
        pub fn $name(ecx: &mut ExtCtxt, sp: Span, meta_item: &MetaItem,
                     annotated: &Annotatable, push: &mut FnMut(Annotatable)) {
            let i_sp = meta_item.span.shorten_to(stringify!($method).len());
            let method = Some(span(Method::$method, i_sp));
            generic_route_decorator(method, ecx, sp, meta_item, annotated, push);
        }
    )
}

method_decorator!(get_decorator, Get);
method_decorator!(put_decorator, Put);
method_decorator!(post_decorator, Post);
method_decorator!(delete_decorator, Delete);
method_decorator!(head_decorator, Head);
method_decorator!(patch_decorator, Patch);

// TODO: Allow this once Diesel incompatibility is fixed.
// method_decorator!(options_decorator, Options);
<|endoftext|>


<commit_before>#[macro_use] extern crate log;
extern crate rusty_raft;
extern crate rand;
extern crate rustc_serialize;

use rand::{thread_rng, Rng};
use rusty_raft::server::{start_server, ServerHandle};
use rusty_raft::client::{RaftConnection};
use rusty_raft::client::state_machine::{
    StateMachine, RaftStateMachine};
use rusty_raft::common::{Config, RaftError};
use std::env::args;
use std::collections::HashMap;
use std::fmt::Debug;
use std::net::SocketAddr;
use std::str;
use std::str::FromStr;
use std::time::Duration;

use std::fs::File;
use std::io::{stdin, stdout, SeekFrom, Error, ErrorKind, Read, BufReader, Seek, BufRead, Cursor, Write};

use rustc_serialize::json;

static USAGE: &'static str = "
Commands:
  server  Starts a server from an initial cluster config.
  client  Starts a client repl, that communicates with
          a particular cluster.

Usage:
  hashmap server <id> <filename>
  hashmap servers <filename>
  hashmap client <filename>

Options:
  -h --help   Show a help message.
";

fn main() {
    // TODO (sydli) make prettier
    let mut args = args();
    if let Some(command) = args.nth(1) {
        if &command == "server" {
            if let (Some(id_str), Some(filename)) =
                   (args.next(), args.next()) {
                if let Ok(id) = id_str.parse::<u64>() {
                    Server::new(id, &cluster_from_file(&filename)).repl();
                    return;
                }
            }
        } else if &command == "client" {
            if let Some(filename) = args.next() {
                Client::new(&cluster_from_file(&filename)).repl();
                return;
            }
        } else if &command == "servers" {
            if let Some(filename) = args.next() {
                Cluster::new(&cluster_from_file(&filename)).repl();
                return;
            }
        }
    }
    warn!("Incorrect usage. \n{}", USAGE);
}

///
/// Automatically builds a repl loop for an object, if it implements |exec|.
/// Each line a user types into the repl is fed to |exec|.
///
/// Default commands:
///     exit    Exits the loop and shuts down associated process.
///     help    Displays the |help| message for more usage info.
trait Repl {

    ///
    /// Processes each input command from the Repl.
    /// Returns true if |command| is formatted correctly.
    ///
    fn exec(&mut self, command: String) -> bool;

    ///
    /// Usage string displayed with the default command "help".
    ///
    fn usage(&self) -> String;

    fn print_usage(&self) {
        println!("\nREPL COMMANDS:\n==============\n{}\n{}\n{}",
                 "exit\n\t\tExits the loop and shuts down associated process.",
                 "help\n\t\tSpits out this message.",
                 self.usage());
    }

    ///
    /// Implementation of the repl.
    fn repl(&mut self) {
        println!("[ Starting repl ]");
        loop {
            print!("> ");
            stdout().flush().unwrap();
            let mut buffer = String::new();
            if stdin().read_line(&mut buffer).is_ok() {
                let words: Vec<String> =
                    buffer.split_whitespace().map(String::from).collect();
                if words.get(0) == Some(&String::from("exit")) { break; }
                if words.get(0) == Some(&String::from("help")) {
                    self.print_usage();
                    continue;
                }
                if !self.exec(buffer.clone()) {
                    println!("Command not recognized.");
                    self.print_usage();
                }
            }
        }
    }
}

struct Server {
    handle: ServerHandle,
}

impl Repl for Server {
    fn exec(&mut self, command: String) -> bool { true }
    fn usage(&self) -> String { String::from("") }
}

impl Server {
    fn new(id: u64, cluster: &HashMap<u64, SocketAddr>) -> Server {
        if !cluster.contains_key(&id) {
            panic!("Initial cluster must contain server id: {}", id);
        }
        Server {
            handle:
                // TODO: Only the first server should put itself in its log file
                start_server(id, Box::new(RaftHashMap { map: HashMap::new() }), *cluster.get(&id).unwrap()).unwrap()
        }
    }
}

struct Cluster {
    servers: HashMap<u64, Server>,
    cluster: HashMap<u64, SocketAddr>,
}

impl Cluster {
    fn new(cluster: &HashMap<u64, SocketAddr>) -> Cluster {
        Cluster {
            servers: cluster.iter()
                .map(|(id, _)| (*id, Server::new(*id, &cluster.clone())))
                .collect::<HashMap<u64, Server>>(),
            cluster: cluster.clone(),
        }
    }

    fn add_server(&mut self, id: u64, addr: SocketAddr) {
        println!("Adding server {}, {}", id, addr);
    }

    fn remove_server(&mut self, id: u64) {
        if !self.cluster.contains_key(&id) {
            println!("Server {} is not in the cluster! Servers: {:?}", id,
                     self.cluster);
        }
        println!("Removing server {}", id);
    }

    fn kill_server(&mut self, id: u64) {
        if !self.servers.contains_key(&id) {
            println!("Server {} is not up right now!", id);
        }
        {
            self.servers.remove(&id).unwrap();
        } // drop server
        println!("Killed server {}", id);
    }

    fn start_server(&mut self, id: u64) {
        if self.servers.contains_key(&id) {
            println!("Server {} is already up!", id);
        }
        self.servers.insert(id, Server::new(id, &self.cluster.clone()));
        println!("Restarted server {}", id);
    }

    fn print_servers(&self) {
        println!("Servers in cluster: {:?}\n Live servers: {:?}",
                 self.cluster, self.servers.keys().collect::<Vec<&u64>>());
    }
}

impl Repl for Cluster {
    fn exec(&mut self, command: String) -> bool {
        let words: Vec<&str> =
            command.split_whitespace().collect();
        let first = words.get(0).map(|x|*x);
        if first == Some("add")  {
            let num = words.get(1).and_then(|x| as_num(*x).ok());
            let addr = words.get(2).and_then(|x| as_addr(*x).ok());
            if num.and(addr).is_none() { return false; }
            self.add_server(num.unwrap(), addr.unwrap());
        } else if first == Some("remove") {
            let num = words.get(1).and_then(|x| as_num(*x).ok());
            if num.is_none() { return false; }
            self.remove_server(num.unwrap());
        } else if first == Some("kill") {
            let num = words.get(1).and_then(|x| as_num(*x).ok());
            if num.is_none() { return false; }
            self.kill_server(num.unwrap());
        } else if first == Some("start") {
            let num = words.get(1).and_then(|x| as_num(*x).ok());
            if num.is_none() { return false; }
            self.start_server(num.unwrap());
        } else if first == Some("list") {
            self.print_servers();
        } else { return false; }
        return true;
    }

    fn usage(&self) -> String {
        String::from(format!(
                "{}\n{}\n{}\n{}\n{}",
                "add <node-id> <node-addr>\tAdds a server to the cluster.",
                "remove <node-id>\tRemoves a server from the cluster.",
                "start <node-id>\tStarts a server from the cluster.",
                "kill <node-id>\tKills a server from the cluster.",
                "list\tLists all cluster servers, and the ones that are live."))
    }
}

struct Client {
    raft: RaftConnection,
}

impl Repl for Client {
    fn exec (&mut self, command: String) -> bool {
        let words: Vec<String> =
            command.split_whitespace().map(String::from).collect();
        self.process_command(words)
    }
    fn usage(&self) -> String {
        String::from(format!(
                "{}\n{}",
                 "get <key>\n\t\tPrints value of <key> in hashmap, if it exists.",
                 "put <key> <value>\n\t\tPuts value of <key> as <value>"))
    }
}

#[derive(RustcDecodable, RustcEncodable)]
struct Put {
    key: String,
    value: String,
}

impl Client {
    fn new(cluster: &HashMap<u64, SocketAddr>) -> Client {
        let connection = RaftConnection::new_with_session(cluster);
        if connection.is_none() {
            println!("Couldn't establish connection to cluster at {:?}", cluster);
            panic!();
        }
        Client { raft: RaftConnection::new_with_session(cluster).unwrap() }
    }

    fn get(&mut self, key: String) -> Result<String, RaftError> {
        self.raft.query(key.as_bytes())
            .and_then(
                |result| str::from_utf8(&result)
                             .map(str::to_string)
                             .map_err(deserialize_error))
    }

    fn put(&mut self, key: String, value: String) -> Result<(), RaftError> {
        json::encode(&Put {key:key, value:value})
            .map_err(serialize_error)
            .and_then(|buffer| self.raft.command(&buffer.as_bytes()))
    }

    // TODO (sydli): make this function less shit
    fn process_command(&mut self, words: Vec<String>)
        -> bool {
        if words.len() == 0 { return true; }
        let ref cmd = words[0];
        if *cmd == String::from("get") {
            if words.len() <= 1 { return false; }
            words.get(1).map(|key| {
                match self.get(key.clone()) {
                    Ok(value) => println!("Value for {} is {}", key, value),
                    Err(err) => println!("Error during get: {:?}", err),
                }
            }).unwrap();
        } else if *cmd == String::from("put") {
            if words.len() <= 2 { return false; }
            words.get(1).map(|key| { words.get(2).map(|val| {
                match self.put(key.clone(), val.clone()) {
                    Ok(()) => println!("Put {} => {} successfully", key, val),
                    Err(err) => println!("Error during put: {:?}", err),
                }
            }).unwrap()}).unwrap();
        } else { return false; }
        return true;
    }
}

fn io_err() -> std::io::Error {
    Error::new(ErrorKind::InvalidData, "File incorrectly formatted")
}

fn as_num(x: &str) -> Result<u64, std::io::Error> {
    String::from(x).parse::<u64>().map_err(|_| io_err())
}

fn as_addr(x: &str) -> Result<SocketAddr, std::io::Error> {
    String::from(x).parse::<SocketAddr>().map_err(|_| io_err())
}

/// Panics on io error (we can't access the cluster info!)
/// TODO (sydli) make io_errs more informative
// TODO(jason): Remove this and bootstrap a dynamic cluster
fn cluster_from_file(filename: &str) -> HashMap<u64, SocketAddr> {
    let file = File::open(filename.clone())
               .expect(&format!("Unable to open file {}", filename));
    let mut lines = BufReader::new(file).lines();
    lines.next().ok_or(io_err())
    .map(|line_or_io_error| line_or_io_error.unwrap())
    .and_then(|x| as_num(&x))
    .and_then(|num| (0..num).map(|_| {
        lines.next().ok_or(io_err())
        .map(|line_or_io_error| line_or_io_error.unwrap())
        .and_then(|node_str| {
            let mut words = node_str.split_whitespace().map(String::from);
            let id = words.next().ok_or(io_err())
                        .and_then(|x| as_num(&x));
            words.next().ok_or(io_err())
                .and_then(|x| as_addr(&x))
                .and_then(move |addr| id.map(|id| (id, addr)))
        })
    }).collect::<Result<Vec<_>, _>>())
    .map(|nodes: Vec<(u64, SocketAddr)>|
        nodes.iter().cloned().collect::<HashMap<u64, SocketAddr>>()
    ).unwrap()
}

struct RaftHashMap {
    map: HashMap<String, String>,
}

fn serialize_error <T: Debug>(error: T) -> RaftError {
        RaftError::ClientError(
            format!("Couldn't serialize object. Error: {:?}", error))
}

fn deserialize_error <T: Debug>(error: T) -> RaftError {
        RaftError::ClientError(
            format!("Couldn't deserialize buffer. Error: {:?}", error))
}

fn key_error(key: &String) -> RaftError {
        RaftError::ClientError(format!("Couldn't find key {}", key))
}

impl StateMachine for RaftHashMap {
    fn command (&mut self, buffer: &[u8]) ->Result<(), RaftError> {
        str::from_utf8(buffer)
            .map_err(deserialize_error)
            .and_then(|string| json::decode(&string)
                                    .map_err(deserialize_error))
            .map(|put: Put|
                 {
                     self.map.insert(put.key, put.value);
                 })
    }

    fn query (& self, buffer: &[u8]) ->Result<Vec<u8>, RaftError> {
        str::from_utf8(buffer)
            .map_err(deserialize_error)
            .and_then(|key| {
                let key = key.to_string();
                self.map.get(&key)
                    .map(|x| x.as_bytes().to_vec())
                    .ok_or(key_error(&key))
            })
    }
}

<commit_msg>example: change warning logging<commit_after>#[macro_use] extern crate log;
extern crate rusty_raft;
extern crate rand;
extern crate rustc_serialize;
extern crate env_logger;

use rand::{thread_rng, Rng};
use rusty_raft::server::{start_server, ServerHandle};
use rusty_raft::client::{RaftConnection};
use rusty_raft::client::state_machine::{
    StateMachine, RaftStateMachine};
use rusty_raft::common::{Config, RaftError};
use std::env::args;
use std::collections::HashMap;
use std::fmt::Debug;
use std::net::SocketAddr;
use std::str;
use std::str::FromStr;
use std::time::Duration;

use std::fs::File;
use std::io::{stdin, stdout, SeekFrom, Error, ErrorKind, Read, BufReader, Seek, BufRead, Cursor, Write};

use rustc_serialize::json;

static USAGE: &'static str = "
Commands:
  server  Starts a server from an initial cluster config.
  client  Starts a client repl, that communicates with
          a particular cluster.

Usage:
  hashmap server <id> <filename>
  hashmap servers <filename>
  hashmap client <filename>

Options:
  -h --help   Show a help message.
";

fn main() {
    env_logger::init().unwrap();
    // TODO (sydli) make prettier
    let mut args = args();
    if let Some(command) = args.nth(1) {
        if &command == "server" {
            if let (Some(id_str), Some(filename)) =
                   (args.next(), args.next()) {
                if let Ok(id) = id_str.parse::<u64>() {
                    Server::new(id, &cluster_from_file(&filename)).repl();
                    return;
                }
            }
        } else if &command == "client" {
            if let Some(filename) = args.next() {
                Client::new(&cluster_from_file(&filename)).repl();
                return;
            }
        } else if &command == "servers" {
            if let Some(filename) = args.next() {
                Cluster::new(&cluster_from_file(&filename)).repl();
                return;
            }
        }
    }
    println!("Incorrect usage. \n{}", USAGE);
}

///
/// Automatically builds a repl loop for an object, if it implements |exec|.
/// Each line a user types into the repl is fed to |exec|.
///
/// Default commands:
///     exit    Exits the loop and shuts down associated process.
///     help    Displays the |help| message for more usage info.
trait Repl {

    ///
    /// Processes each input command from the Repl.
    /// Returns true if |command| is formatted correctly.
    ///
    fn exec(&mut self, command: String) -> bool;

    ///
    /// Usage string displayed with the default command "help".
    ///
    fn usage(&self) -> String;

    fn print_usage(&self) {
        println!("\nREPL COMMANDS:\n==============\n{}\n{}\n{}",
                 "exit\n\t\tExits the loop and shuts down associated process.",
                 "help\n\t\tSpits out this message.",
                 self.usage());
    }

    ///
    /// Implementation of the repl.
    fn repl(&mut self) {
        println!("[ Starting repl ]");
        loop {
            print!("> ");
            stdout().flush().unwrap();
            let mut buffer = String::new();
            if stdin().read_line(&mut buffer).is_ok() {
                let words: Vec<String> =
                    buffer.split_whitespace().map(String::from).collect();
                if words.get(0) == Some(&String::from("exit")) { break; }
                if words.get(0) == Some(&String::from("help")) {
                    self.print_usage();
                    continue;
                }
                if !self.exec(buffer.clone()) {
                    println!("Command not recognized.");
                    self.print_usage();
                }
            }
        }
    }
}

struct Server {
    handle: ServerHandle,
}

impl Repl for Server {
    fn exec(&mut self, command: String) -> bool { true }
    fn usage(&self) -> String { String::from("") }
}

impl Server {
    fn new(id: u64, cluster: &HashMap<u64, SocketAddr>) -> Server {
        if !cluster.contains_key(&id) {
            panic!("Initial cluster must contain server id: {}", id);
        }
        Server {
            handle:
                // TODO: Only the first server should put itself in its log file
                start_server(id, Box::new(RaftHashMap { map: HashMap::new() }), *cluster.get(&id).unwrap()).unwrap()
        }
    }
}

struct Cluster {
    servers: HashMap<u64, Server>,
    cluster: HashMap<u64, SocketAddr>,
}

impl Cluster {
    fn new(cluster: &HashMap<u64, SocketAddr>) -> Cluster {
        Cluster {
            servers: cluster.iter()
                .map(|(id, _)| (*id, Server::new(*id, &cluster.clone())))
                .collect::<HashMap<u64, Server>>(),
            cluster: cluster.clone(),
        }
    }

    fn add_server(&mut self, id: u64, addr: SocketAddr) {
        println!("Adding server {}, {}", id, addr);
    }

    fn remove_server(&mut self, id: u64) {
        if !self.cluster.contains_key(&id) {
            println!("Server {} is not in the cluster! Servers: {:?}", id,
                     self.cluster);
        }
        println!("Removing server {}", id);
    }

    fn kill_server(&mut self, id: u64) {
        if !self.servers.contains_key(&id) {
            println!("Server {} is not up right now!", id);
        }
        {
            self.servers.remove(&id).unwrap();
        } // drop server
        println!("Killed server {}", id);
    }

    fn start_server(&mut self, id: u64) {
        if self.servers.contains_key(&id) {
            println!("Server {} is already up!", id);
        }
        self.servers.insert(id, Server::new(id, &self.cluster.clone()));
        println!("Restarted server {}", id);
    }

    fn print_servers(&self) {
        println!("Servers in cluster: {:?}\n Live servers: {:?}",
                 self.cluster, self.servers.keys().collect::<Vec<&u64>>());
    }
}

impl Repl for Cluster {
    fn exec(&mut self, command: String) -> bool {
        let words: Vec<&str> =
            command.split_whitespace().collect();
        let first = words.get(0).map(|x|*x);
        if first == Some("add")  {
            let num = words.get(1).and_then(|x| as_num(*x).ok());
            let addr = words.get(2).and_then(|x| as_addr(*x).ok());
            if num.and(addr).is_none() { return false; }
            self.add_server(num.unwrap(), addr.unwrap());
        } else if first == Some("remove") {
            let num = words.get(1).and_then(|x| as_num(*x).ok());
            if num.is_none() { return false; }
            self.remove_server(num.unwrap());
        } else if first == Some("kill") {
            let num = words.get(1).and_then(|x| as_num(*x).ok());
            if num.is_none() { return false; }
            self.kill_server(num.unwrap());
        } else if first == Some("start") {
            let num = words.get(1).and_then(|x| as_num(*x).ok());
            if num.is_none() { return false; }
            self.start_server(num.unwrap());
        } else if first == Some("list") {
            self.print_servers();
        } else { return false; }
        return true;
    }

    fn usage(&self) -> String {
        String::from(format!(
                "{}\n{}\n{}\n{}\n{}",
                "add <node-id> <node-addr>\tAdds a server to the cluster.",
                "remove <node-id>\tRemoves a server from the cluster.",
                "start <node-id>\tStarts a server from the cluster.",
                "kill <node-id>\tKills a server from the cluster.",
                "list\tLists all cluster servers, and the ones that are live."))
    }
}

struct Client {
    raft: RaftConnection,
}

impl Repl for Client {
    fn exec (&mut self, command: String) -> bool {
        let words: Vec<String> =
            command.split_whitespace().map(String::from).collect();
        self.process_command(words)
    }
    fn usage(&self) -> String {
        String::from(format!(
                "{}\n{}",
                 "get <key>\n\t\tPrints value of <key> in hashmap, if it exists.",
                 "put <key> <value>\n\t\tPuts value of <key> as <value>"))
    }
}

#[derive(RustcDecodable, RustcEncodable)]
struct Put {
    key: String,
    value: String,
}

impl Client {
    fn new(cluster: &HashMap<u64, SocketAddr>) -> Client {
        let connection = RaftConnection::new_with_session(cluster);
        if connection.is_none() {
            println!("Couldn't establish connection to cluster at {:?}", cluster);
            panic!();
        }
        Client { raft: RaftConnection::new_with_session(cluster).unwrap() }
    }

    fn get(&mut self, key: String) -> Result<String, RaftError> {
        self.raft.query(key.as_bytes())
            .and_then(
                |result| str::from_utf8(&result)
                             .map(str::to_string)
                             .map_err(deserialize_error))
    }

    fn put(&mut self, key: String, value: String) -> Result<(), RaftError> {
        json::encode(&Put {key:key, value:value})
            .map_err(serialize_error)
            .and_then(|buffer| self.raft.command(&buffer.as_bytes()))
    }

    // TODO (sydli): make this function less shit
    fn process_command(&mut self, words: Vec<String>)
        -> bool {
        if words.len() == 0 { return true; }
        let ref cmd = words[0];
        if *cmd == String::from("get") {
            if words.len() <= 1 { return false; }
            words.get(1).map(|key| {
                match self.get(key.clone()) {
                    Ok(value) => println!("Value for {} is {}", key, value),
                    Err(err) => println!("Error during get: {:?}", err),
                }
            }).unwrap();
        } else if *cmd == String::from("put") {
            if words.len() <= 2 { return false; }
            words.get(1).map(|key| { words.get(2).map(|val| {
                match self.put(key.clone(), val.clone()) {
                    Ok(()) => println!("Put {} => {} successfully", key, val),
                    Err(err) => println!("Error during put: {:?}", err),
                }
            }).unwrap()}).unwrap();
        } else { return false; }
        return true;
    }
}

fn io_err() -> std::io::Error {
    Error::new(ErrorKind::InvalidData, "File incorrectly formatted")
}

fn as_num(x: &str) -> Result<u64, std::io::Error> {
    String::from(x).parse::<u64>().map_err(|_| io_err())
}

fn as_addr(x: &str) -> Result<SocketAddr, std::io::Error> {
    String::from(x).parse::<SocketAddr>().map_err(|_| io_err())
}

/// Panics on io error (we can't access the cluster info!)
/// TODO (sydli) make io_errs more informative
// TODO(jason): Remove this and bootstrap a dynamic cluster
fn cluster_from_file(filename: &str) -> HashMap<u64, SocketAddr> {
    let file = File::open(filename.clone())
               .expect(&format!("Unable to open file {}", filename));
    let mut lines = BufReader::new(file).lines();
    lines.next().ok_or(io_err())
    .map(|line_or_io_error| line_or_io_error.unwrap())
    .and_then(|x| as_num(&x))
    .and_then(|num| (0..num).map(|_| {
        lines.next().ok_or(io_err())
        .map(|line_or_io_error| line_or_io_error.unwrap())
        .and_then(|node_str| {
            let mut words = node_str.split_whitespace().map(String::from);
            let id = words.next().ok_or(io_err())
                        .and_then(|x| as_num(&x));
            words.next().ok_or(io_err())
                .and_then(|x| as_addr(&x))
                .and_then(move |addr| id.map(|id| (id, addr)))
        })
    }).collect::<Result<Vec<_>, _>>())
    .map(|nodes: Vec<(u64, SocketAddr)>|
        nodes.iter().cloned().collect::<HashMap<u64, SocketAddr>>()
    ).unwrap()
}

struct RaftHashMap {
    map: HashMap<String, String>,
}

fn serialize_error <T: Debug>(error: T) -> RaftError {
        RaftError::ClientError(
            format!("Couldn't serialize object. Error: {:?}", error))
}

fn deserialize_error <T: Debug>(error: T) -> RaftError {
        RaftError::ClientError(
            format!("Couldn't deserialize buffer. Error: {:?}", error))
}

fn key_error(key: &String) -> RaftError {
        RaftError::ClientError(format!("Couldn't find key {}", key))
}

impl StateMachine for RaftHashMap {
    fn command (&mut self, buffer: &[u8]) ->Result<(), RaftError> {
        str::from_utf8(buffer)
            .map_err(deserialize_error)
            .and_then(|string| json::decode(&string)
                                    .map_err(deserialize_error))
            .map(|put: Put|
                 {
                     self.map.insert(put.key, put.value);
                 })
    }

    fn query (& self, buffer: &[u8]) ->Result<Vec<u8>, RaftError> {
        str::from_utf8(buffer)
            .map_err(deserialize_error)
            .and_then(|key| {
                let key = key.to_string();
                self.map.get(&key)
                    .map(|x| x.as_bytes().to_vec())
                    .ok_or(key_error(&key))
            })
    }
}

<|endoftext|>


<commit_before>//
//  0 1 0  Mnemosyne: a functional systems programming language.
//  0 0 1  (c) 2015 Hawk Weisman
//  1 1 1  hi@hawkweisman.me
//
//  Mnemosyne is released under the MIT License. Please refer to
//  the LICENSE file at the top-level directory of this distribution
//  or at https://github.com/hawkw/mnemosyne/.
//
use rustc::lib::llvm;
use rustc::lib::llvm::*;

use std::ffi::CString;
use std::mem::transmute;

use libc::{c_char, c_uint};

use ::errors::{ExpectICE, UnwrapICE};

// pub struct Context(llvm::ContextRef);
//
// pub struct Builder(llvm::BuilderRef);

/// because we are in the Raw Pointer Sadness Zone (read: unsafe),
/// it is necessary that we assert that everything exists.
macro_rules! not_null {
    ($target:expr) => ({
        let e = $target;
        if e.is_null() {
            ice!( "assertion failed: {} returned null!"
                , stringify!($target)
                );
        } else { e }
    })
}

trait LLVMWrapper {
    type Ref;
    fn to_ref(&self) -> Self::Ref;
    fn from_ref(r: Self::Ref) -> Self;
}

macro_rules! llvm_wrapper {
    ( $($name:ident wrapping $wrapped:path),*) => {$(
        pub struct $name ($wrapped);

        impl LLVMWrapper for $name {
            type Ref = $wrapped;

            fn to_ref(&self) -> Self::Ref {
                not_null!(self.0)
            }

            fn from_ref(r: $wrapped) -> Self {
                $name( not_null!(r) )
            }
        }
    )*};
    ( $($name:ident wrapping $wrapped:path, dropped by $drop:path),*) => {$(
        llvm_wrapper!{ $name wrapping $wrapped }

        impl Drop for $name {
            fn drop(&mut self) {
                unsafe { $drop(self.0) }
            }
        }
    )*}
}

llvm_wrapper! {
    Context wrapping llvm::ContextRef, dropped by llvm::LLVMContextDispose,
    Builder wrapping llvm::BuilderRef, dropped by llvm::LLVMDisposeBuilder
}

llvm_wrapper! {
    BasicBlock wrapping llvm::BasicBlockRef,
    Value wrapping llvm::ValueRef
}

impl Context {
    /// Construct a new Builder within this `Context`.
    pub fn create_builder(&self) -> Builder {
        unsafe {
            Builder::from_ref(LLVMCreateBuilderInContext(self.to_ref()))
        }
    }
}

impl Builder {
    //---- positioning --------------------------------------------------------
    /// Wrapper for `LLVMPositionBuilder`.
    pub fn position(&mut self, block: &mut BasicBlock, inst: &Value)
                   -> &mut Self {
        unsafe {
            LLVMPositionBuilder(self.to_ref(), block.to_ref(), inst.to_ref());
        }
        self
    }

    /// Wrapper for `LLVMPositionBuilderBefore`.
    pub fn position_before(&mut self, inst: &Value) -> &mut Self {
        unsafe { LLVMPositionBuilderBefore(self.to_ref(), inst.to_ref()) }
        self
    }

    /// Wrapper for `LLVMPositionBuilderAtEnd`.
    pub fn position_at_end(&mut self, block: &mut BasicBlock) -> &mut Self {
        unsafe { LLVMPositionBuilderAtEnd(self.to_ref(), block.to_ref()) }
        self
    }

    //---- insertion ----------------------------------------------------------
    pub fn get_insert_block(&mut self) -> BasicBlock {
        unsafe { BasicBlock::from_ref(LLVMGetInsertBlock(self.to_ref())) }
    }

    pub fn clear_insertion_position(&mut self) -> &mut Self {
        unsafe { LLVMClearInsertionPosition(self.to_ref()) }
        self
    }

    pub fn insert(&mut self, inst: &mut Value) -> &mut Self {
        unsafe { LLVMInsertIntoBuilder(self.to_ref(), inst.to_ref()) }
        self
    }

    pub fn insert_with_name(&mut self, inst: &mut Value, name: &str)
                            -> &mut Self {
        let cname = CString::new(name).expect_ice(
                    format!("Couldn't create CString for {}", name).as_ref());
        unsafe {
            LLVMInsertIntoBuilderWithName( self.to_ref()
                                         , inst.to_ref()
                                         , cname.as_ptr() as *const c_char)
        }
        self
    }
    //---- building ----------------------------------------------------------
    /// Create a `ret void` return instruction.
    pub fn build_ret_void(&mut self) -> Value {
        unsafe { Value::from_ref( LLVMBuildRetVoid(self.to_ref()) ) }
    }

    /// Create a `ret <value>` instruction.
    ///
    /// # Arguments:
    ///   - `v`: the `Value` to return
    pub fn build_ret(&mut self, v: &Value) -> Value {
        unsafe {
            Value::from_ref( LLVMBuildRet(self.to_ref(), v.to_ref()) )
        }
    }

    /// Create an unconditional branch `br label X` instruction.
    ///
    /// # Arguments:
    ///   - `dest` the `BasicBlock` to branch to
    pub fn build_br(&mut self, dest: &BasicBlock) -> Value {
        unsafe {
            Value::from_ref( LLVMBuildBr(self.to_ref(), dest.to_ref()) )
        }
    }

    /// Create a conditional branch instruction.
    ///
    /// # Returns:
    /// A conditional branch instruction of the form
    /// `br $condition, $then_block, $else_block`.
    ///
    /// # Arguments:
    ///   - `condition`: the condition to test
    ///   - `then_block`: the block to branch to if the condition is true
    ///   - `else_block`: the block to branch to if the condition is false
    pub fn build_cond_br( &mut self
                        , condition: Value
                        , then_block: &BasicBlock
                        , else_block: &BasicBlock )
                        -> Value {
        unsafe {
            let val = LLVMBuildCondBr( self.to_ref()
                                     , condition.to_ref()
                                     , then_block.to_ref()
                                     , else_block.to_ref() );
            Value::from_ref(val)
        }
    }

    /// Create a switch instruction.
    ///
    /// # Returns:
    /// A switch instruction with the specified value and default destination.
    ///
    /// # Arguments:
    ///   - `on`: the `Value` to switch on
    ///   - `else_block`: a `BasicBlock` representing the default destination
    ///   - `num_cases`: a hint towards the number of cases in the switch
    ///                  expression (for more efficient allocation)
    pub fn build_switch_br( &mut self
                          , on: Value
                          , else_block: &BasicBlock
                          , num_cases: u32 )
                          -> Value {
        unsafe {
            Value::from_ref(LLVMBuildSwitch( self.to_ref()
                                            , on.to_ref()
                                            , else_block.to_ref()
                                            , num_cases))
        }
    }

    pub fn build_invoke( &mut self
                       , function: Value
                       , args: &mut [Value]
                       , then_block: &BasicBlock
                       , catch_block: &BasicBlock
                       , name: &str )
                       -> Value {
        let cname = CString::new(name).unwrap_ice().as_ptr();
        unsafe {
            let args_ref = transmute::<&mut [Value], &mut [ValueRef]>(args)
                            .as_ptr();
            let val = LLVMBuildInvoke( self.to_ref()
                                     , function.to_ref()
                                     , args_ref, args.len() as c_uint
                                     , then_block.to_ref()
                                     , catch_block.to_ref()
                                     , cname as *const c_char);
            Value::from_ref(val)
        }
    }

}
<commit_msg>[core] Add unreachable and resume builders<commit_after>//
//  0 1 0  Mnemosyne: a functional systems programming language.
//  0 0 1  (c) 2015 Hawk Weisman
//  1 1 1  hi@hawkweisman.me
//
//  Mnemosyne is released under the MIT License. Please refer to
//  the LICENSE file at the top-level directory of this distribution
//  or at https://github.com/hawkw/mnemosyne/.
//
use rustc::lib::llvm;
use rustc::lib::llvm::*;

use std::ffi::CString;
use std::mem::transmute;

use libc::{c_char, c_uint};

use ::errors::{ExpectICE, UnwrapICE};

// pub struct Context(llvm::ContextRef);
//
// pub struct Builder(llvm::BuilderRef);

/// because we are in the Raw Pointer Sadness Zone (read: unsafe),
/// it is necessary that we assert that everything exists.
macro_rules! not_null {
    ($target:expr) => ({
        let e = $target;
        if e.is_null() {
            ice!( "assertion failed: {} returned null!"
                , stringify!($target)
                );
        } else { e }
    })
}

trait LLVMWrapper {
    type Ref;
    fn to_ref(&self) -> Self::Ref;
    fn from_ref(r: Self::Ref) -> Self;
}

macro_rules! llvm_wrapper {
    ( $($name:ident wrapping $wrapped:path),*) => {$(
        pub struct $name ($wrapped);

        impl LLVMWrapper for $name {
            type Ref = $wrapped;

            fn to_ref(&self) -> Self::Ref {
                not_null!(self.0)
            }

            fn from_ref(r: $wrapped) -> Self {
                $name( not_null!(r) )
            }
        }
    )*};
    ( $($name:ident wrapping $wrapped:path, dropped by $drop:path),*) => {$(
        llvm_wrapper!{ $name wrapping $wrapped }

        impl Drop for $name {
            fn drop(&mut self) {
                unsafe { $drop(self.0) }
            }
        }
    )*}
}

llvm_wrapper! {
    Context wrapping llvm::ContextRef, dropped by llvm::LLVMContextDispose,
    Builder wrapping llvm::BuilderRef, dropped by llvm::LLVMDisposeBuilder
}

llvm_wrapper! {
    BasicBlock wrapping llvm::BasicBlockRef,
    Value wrapping llvm::ValueRef
}

impl Context {
    /// Construct a new Builder within this `Context`.
    pub fn create_builder(&self) -> Builder {
        unsafe {
            Builder::from_ref(LLVMCreateBuilderInContext(self.to_ref()))
        }
    }
}

impl Builder {
    //---- positioning --------------------------------------------------------
    /// Wrapper for `LLVMPositionBuilder`.
    pub fn position(&mut self, block: &mut BasicBlock, inst: &Value)
                   -> &mut Self {
        unsafe {
            LLVMPositionBuilder(self.to_ref(), block.to_ref(), inst.to_ref());
        }
        self
    }

    /// Wrapper for `LLVMPositionBuilderBefore`.
    pub fn position_before(&mut self, inst: &Value) -> &mut Self {
        unsafe { LLVMPositionBuilderBefore(self.to_ref(), inst.to_ref()) }
        self
    }

    /// Wrapper for `LLVMPositionBuilderAtEnd`.
    pub fn position_at_end(&mut self, block: &mut BasicBlock) -> &mut Self {
        unsafe { LLVMPositionBuilderAtEnd(self.to_ref(), block.to_ref()) }
        self
    }

    //---- insertion ----------------------------------------------------------
    pub fn get_insert_block(&mut self) -> BasicBlock {
        unsafe { BasicBlock::from_ref(LLVMGetInsertBlock(self.to_ref())) }
    }

    pub fn clear_insertion_position(&mut self) -> &mut Self {
        unsafe { LLVMClearInsertionPosition(self.to_ref()) }
        self
    }

    pub fn insert(&mut self, inst: &mut Value) -> &mut Self {
        unsafe { LLVMInsertIntoBuilder(self.to_ref(), inst.to_ref()) }
        self
    }

    pub fn insert_with_name(&mut self, inst: &mut Value, name: &str)
                            -> &mut Self {
        let cname = CString::new(name).expect_ice(
                    format!("Couldn't create CString for {}", name).as_ref());
        unsafe {
            LLVMInsertIntoBuilderWithName( self.to_ref()
                                         , inst.to_ref()
                                         , cname.as_ptr() as *const c_char)
        }
        self
    }
    //---- building ----------------------------------------------------------
    /// Create a `ret void` return instruction.
    pub fn build_ret_void(&mut self) -> Value {
        unsafe { Value::from_ref( LLVMBuildRetVoid(self.to_ref()) ) }
    }

    /// Create a `ret <value>` instruction.
    ///
    /// # Arguments
    ///
    ///  + `v`: the `Value` to return
    pub fn build_ret(&mut self, v: &Value) -> Value {
        unsafe {
            Value::from_ref( LLVMBuildRet(self.to_ref(), v.to_ref()) )
        }
    }

    /// Create an unconditional branch `br label X` instruction.
    ///
    /// # Arguments
    ///
    ///  + `dest` the `BasicBlock` to branch to.
    ///
    /// # Return Value
    ///  An unconditional branch `br` instruction.
    pub fn build_br(&mut self, dest: &BasicBlock) -> Value {
        unsafe {
            Value::from_ref( LLVMBuildBr(self.to_ref(), dest.to_ref()) )
        }
    }

    /// Create a conditional branch instruction.
    ///
    /// # Arguments
    ///
    ///  + `condition`: the condition to test
    ///  + `then_block`: the block to branch to if the condition is true
    ///  + `else_block`: the block to branch to if the condition is false
    ///
    ///  # Returns Value
    ///
    /// A conditional branch instruction of the form
    /// `br $condition, $then_block, $else_block`.
    pub fn build_cond_br( &mut self
                        , condition: Value
                        , then_block: &BasicBlock
                        , else_block: &BasicBlock )
                        -> Value {
        unsafe {
            let val = LLVMBuildCondBr( self.to_ref()
                                     , condition.to_ref()
                                     , then_block.to_ref()
                                     , else_block.to_ref() );
            Value::from_ref(val)
        }
    }

    /// Create a switch instruction.
    ///
    /// # Arguments
    ///
    ///  + `on`: the `Value` to switch on
    ///  + `else_block`: a `BasicBlock` representing the default destination
    ///  + `num_cases`: a hint towards the number of cases in the switch
    ///                 expression (for more efficient allocation)
    ///
    /// # Return Value
    ///
    /// A switch instruction with the specified value and default destination.
    pub fn build_switch_br( &mut self
                          , on: Value
                          , else_block: &BasicBlock
                          , num_cases: u32 )
                          -> Value {
        unsafe {
            Value::from_ref(LLVMBuildSwitch( self.to_ref()
                                            , on.to_ref()
                                            , else_block.to_ref()
                                            , num_cases))
        }
    }

    /// Create a function invocation instruction.
    ///
    /// # Arguments
    ///
    ///  + `function`: the function to invoke
    ///  + `args': the arguments to `function`
    ///  + `then_block`:
    ///  + `catch_block`:
    ///  + `name`: the name of the instruction.
    ///
    /// # Return Value
    ///
    /// A function invocation instruction.
    pub fn build_invoke( &mut self
                       , function: Value
                       , args: &mut [Value]
                       , then_block: &BasicBlock
                       , catch_block: &BasicBlock
                       , name: &str )
                       -> Value {
        let cname = CString::new(name).unwrap_ice().as_ptr();
        unsafe {
            let args_ref = transmute::<&mut [Value], &mut [ValueRef]>(args)
                            .as_ptr();
            let val = LLVMBuildInvoke( self.to_ref()
                                     , function.to_ref()
                                     , args_ref, args.len() as c_uint
                                     , then_block.to_ref()
                                     , catch_block.to_ref()
                                     , cname as *const c_char);
            Value::from_ref(val)
        }
    }

    pub fn build_resume(&mut self, ex: Value) -> Value {
        unsafe { Value::from_ref(LLVMBuildResume(self.to_ref(), ex.to_ref())) }
    }

    pub fn build_unreachable(&mut self) -> Value {
        unsafe { Value::from_ref(LLVMBuildUnreachable(self.to_ref()) }
    }

}
<|endoftext|>


<commit_before>extern crate rotor;
extern crate rotor_http;
extern crate argparse;
extern crate url;
extern crate env_logger;

use std::io::{stdout, stderr};
use std::io::Write;
use std::net::ToSocketAddrs;
use std::time::Duration;
use std::process::exit;

use url::Url;
use url::SchemeData::Relative;
use argparse::{ArgumentParser, Store};
use rotor::{Scope, Time};
use rotor_http::client::{connect_tcp, Request, Head, Client, RecvMode};
use rotor_http::client::{Connection, Requester, Task, Version, ResponseError};

struct Context;

struct Cli(Option<Url>);
struct Req(Url);

impl Client for Cli {
    type Requester = Req;
    type Seed = Url;
    fn create(seed: Self::Seed,
        _scope: &mut Scope<<Self::Requester as Requester>::Context>)
        -> Self
    {
        Cli(Some(seed))
    }
    fn connection_idle(mut self, _conn: &Connection,
        scope: &mut Scope<Context>)
        -> Task<Cli>
    {
        match self.0.take() {
            Some(url) => Task::Request(Cli(None), Req(url)),
            None => {
                scope.shutdown_loop();
                Task::Close
            }
        }
    }
    fn wakeup(self,
        _connection: &Connection,
        _scope: &mut Scope<<Self::Requester as Requester>::Context>)
        -> Task<Cli>
    {
        unimplemented!();
    }
    fn timeout(self,
        _connection: &Connection,
        _scope: &mut Scope<<Self::Requester as Requester>::Context>)
        -> Task<Cli>
    {
        unimplemented!();
    }
}

impl Requester for Req {
    type Context = Context;
    fn prepare_request(self, req: &mut Request,
        _scope: &mut Scope<Self::Context>)
        -> Option<Self>
    {
        req.start("GET", &self.0.serialize_path().unwrap(), Version::Http11);
        req.add_header("Host", self.0.domain().unwrap().as_bytes()).unwrap();
        req.done_headers().unwrap();
        req.done();
        Some(self)
    }
    fn headers_received(self, head: Head, _request: &mut Request,
        scope: &mut Scope<Self::Context>)
        -> Option<(Self, RecvMode, Time)>
    {
        println!("----- Headers -----");
        println!("Status: {} {}", head.code, head.reason);
        for header in head.headers {
            println!("{}: {}", header.name,
                String::from_utf8_lossy(header.value));
        }
        Some((self,  RecvMode::Buffered(1 << 20),
            scope.now() + Duration::new(1000, 0)))
    }
    fn response_received(self, data: &[u8], _request: &mut Request,
        _scope: &mut Scope<Self::Context>)
    {
        println!("----- Response -----");
        stdout().write_all(data).unwrap();
        if data.last() != Some(&b'\n') {
            println!("");
        }
    }
    fn response_chunk(self, _chunk: &[u8], _request: &mut Request,
        _scope: &mut Scope<Self::Context>)
        -> Option<Self>
    {
        unreachable!();
    }
    fn response_end(self, _request: &mut Request,
        _scope: &mut Scope<Self::Context>)
    {
        unreachable!();
    }
    fn timeout(self, _request: &mut Request, _scope: &mut Scope<Self::Context>)
        -> Option<(Self, Time)>
    {
        unreachable!();
    }
    fn wakeup(self, _request: &mut Request, _scope: &mut Scope<Self::Context>)
        -> Option<Self>
    {
        unimplemented!();
    }
    fn bad_response(self, err: &ResponseError, _scope: &mut Scope<Context>)
    {
        writeln!(&mut stderr(), "----- Bad response: {} -----", err).ok();
        exit(1);
    }
}

fn main() {
    env_logger::init().unwrap();
    let mut url = Url::parse(
        "http://info.cern.ch/hypertext/WWW/TheProject.html").unwrap();
    {
        let mut ap = ArgumentParser::new();
        ap.refer(&mut url)
            .add_argument("url", Store, "Url to fetch");
        ap.parse_args_or_exit();
    }
    if &url.scheme != "http" {
        writeln!(&mut stderr(), "Only 'http://' urls are supported for now")
            .ok();
        exit(1);
    }
    let addr = match url.scheme_data {
        Relative(ref scheme) => {
            (scheme.domain().unwrap(), scheme.port_or_default().unwrap())
                .to_socket_addrs().unwrap().next().unwrap()
        }
        _ => unreachable!(),
    };
    let creator = rotor::Loop::new(&rotor::Config::new()).unwrap();
    let mut loop_inst = creator.instantiate(Context);
    loop_inst.add_machine_with(|scope| {
        connect_tcp::<Cli>(scope, &addr, url)
    }).unwrap();
    loop_inst.run().unwrap();
}
<commit_msg>fix(examples/client): Handle ip4 addresses<commit_after>extern crate rotor;
extern crate rotor_http;
extern crate argparse;
extern crate url;
extern crate env_logger;

use std::io::{stdout, stderr};
use std::io::Write;
use std::net::ToSocketAddrs;
use std::time::Duration;
use std::process::exit;

use url::{Url, Host};
use url::SchemeData::Relative;
use argparse::{ArgumentParser, Store};
use rotor::{Scope, Time};
use rotor_http::client::{connect_tcp, Request, Head, Client, RecvMode};
use rotor_http::client::{Connection, Requester, Task, Version, ResponseError};

struct Context;

struct Cli(Option<Url>);
struct Req(Url);

impl Client for Cli {
    type Requester = Req;
    type Seed = Url;
    fn create(seed: Self::Seed,
        _scope: &mut Scope<<Self::Requester as Requester>::Context>)
        -> Self
    {
        Cli(Some(seed))
    }
    fn connection_idle(mut self, _conn: &Connection,
        scope: &mut Scope<Context>)
        -> Task<Cli>
    {
        match self.0.take() {
            Some(url) => Task::Request(Cli(None), Req(url)),
            None => {
                scope.shutdown_loop();
                Task::Close
            }
        }
    }
    fn wakeup(self,
        _connection: &Connection,
        _scope: &mut Scope<<Self::Requester as Requester>::Context>)
        -> Task<Cli>
    {
        unimplemented!();
    }
    fn timeout(self,
        _connection: &Connection,
        _scope: &mut Scope<<Self::Requester as Requester>::Context>)
        -> Task<Cli>
    {
        unimplemented!();
    }
}

impl Requester for Req {
    type Context = Context;
    fn prepare_request(self, req: &mut Request,
        _scope: &mut Scope<Self::Context>)
        -> Option<Self>
    {
        req.start("GET", &self.0.serialize_path().unwrap(), Version::Http11);
        req.add_header("Host", self.0.serialize_host().unwrap().as_bytes()).unwrap();
        req.done_headers().unwrap();
        req.done();
        Some(self)
    }
    fn headers_received(self, head: Head, _request: &mut Request,
        scope: &mut Scope<Self::Context>)
        -> Option<(Self, RecvMode, Time)>
    {
        println!("----- Headers -----");
        println!("Status: {} {}", head.code, head.reason);
        for header in head.headers {
            println!("{}: {}", header.name,
                String::from_utf8_lossy(header.value));
        }
        Some((self,  RecvMode::Buffered(1 << 20),
            scope.now() + Duration::new(1000, 0)))
    }
    fn response_received(self, data: &[u8], _request: &mut Request,
        _scope: &mut Scope<Self::Context>)
    {
        println!("----- Response -----");
        stdout().write_all(data).unwrap();
        if data.last() != Some(&b'\n') {
            println!("");
        }
    }
    fn response_chunk(self, _chunk: &[u8], _request: &mut Request,
        _scope: &mut Scope<Self::Context>)
        -> Option<Self>
    {
        unreachable!();
    }
    fn response_end(self, _request: &mut Request,
        _scope: &mut Scope<Self::Context>)
    {
        unreachable!();
    }
    fn timeout(self, _request: &mut Request, _scope: &mut Scope<Self::Context>)
        -> Option<(Self, Time)>
    {
        unreachable!();
    }
    fn wakeup(self, _request: &mut Request, _scope: &mut Scope<Self::Context>)
        -> Option<Self>
    {
        unimplemented!();
    }
    fn bad_response(self, err: &ResponseError, _scope: &mut Scope<Context>)
    {
        writeln!(&mut stderr(), "----- Bad response: {} -----", err).ok();
        exit(1);
    }
}

fn main() {
    env_logger::init().unwrap();
    let mut url = Url::parse(
        "http://info.cern.ch/hypertext/WWW/TheProject.html").unwrap();
    {
        let mut ap = ArgumentParser::new();
        ap.refer(&mut url)
            .add_argument("url", Store, "Url to fetch");
        ap.parse_args_or_exit();
    }
    if &url.scheme != "http" {
        writeln!(&mut stderr(), "Only 'http://' urls are supported for now")
            .ok();
        exit(1);
    }
    let addr = match url.scheme_data {
        Relative(ref scheme) => {
            // Can't implement as trait because of E0117
            let port = scheme.port_or_default().unwrap();
            match scheme.host {
                Host::Domain(ref d) => (d.as_str(), port).to_socket_addrs().unwrap().next().unwrap(),
                Host::Ipv4(ref a) => (*a, port).to_socket_addrs().unwrap().next().unwrap(),
                Host::Ipv6(ref a) => (*a, port).to_socket_addrs().unwrap().next().unwrap(),
            }
        }
        _ => unreachable!(),
    };
    let creator = rotor::Loop::new(&rotor::Config::new()).unwrap();
    let mut loop_inst = creator.instantiate(Context);
    loop_inst.add_machine_with(|scope| {
        connect_tcp::<Cli>(scope, &addr, url)
    }).unwrap();
    loop_inst.run().unwrap();
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate flac;
extern crate hound;
extern crate nom;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::Stream;

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

const USAGE: &'static str = "
Usage: decode <input> <output>
       decode <input>... <dir>
       decode --help

Options:
  -h, --help   Show this message.
";

#[derive(RustcDecodable)]
struct Arguments {
  arg_input: Vec<String>,
  arg_output: Option<String>,
  arg_dir: Option<String>,
}

fn decode_file(input_file: &str, output_file: &str)
               -> Result<(), hound::Error> {
  let mut stream = try! {
    Stream::from_file(input_file).map_err(hound::Error::IoError)
  };
  let info       = stream.info();
  let frames_len = stream.frames.len();

  let spec = hound::WavSpec {
    channels: info.channels as u16,
    sample_rate: info.sample_rate,
    bits_per_sample: info.bits_per_sample as u16,
  };

  let mut output = try!(hound::WavWriter::create(output_file, spec));

  for _ in 0..frames_len {
    if let Some(buffer) = stream.next_frame() {
      let buffer_size = buffer.len();
      let block_size  = buffer_size / 2;
      let left        = &buffer[0..block_size];
      let right       = &buffer[block_size..buffer_size];

      for i in 0..block_size {
        try!(output.write_sample(left[i]));
        try!(output.write_sample(right[i]));
      }
    } else {
      break;
    }
  }

  output.finalize()
}

fn to_output_file(buffer: &mut PathBuf, path: &Path, directory: &str)
                  -> Result<(), hound::Error> {
  buffer.push(directory);

  path.file_name().map(|name| {
    buffer.push(name);
    buffer.set_extension("wav");
  }).ok_or_else(|| {
    let kind    = io::ErrorKind::NotFound;
    let message = "no file name found";
    let error   = io::Error::new(kind, message);

    hound::Error::IoError(error)
  })
}

fn decode_all_files(input_files: &Vec<String>, directory: &str)
                    -> Result<(), hound::Error> {
  let dir_path = Path::new(directory);

  if !dir_path.exists() {
    try!(fs::create_dir(dir_path).map_err(hound::Error::IoError))
  }

  for ref input_file in input_files {
    let mut buffer = PathBuf::new();
    let path       = Path::new(input_file);

    try!(to_output_file(&mut buffer, path, directory));

    let output_file = try! {
      buffer.to_str().ok_or_else(|| {
        let kind    = io::ErrorKind::InvalidInput;
        let message = "invalid unicode with file path";
        let error   = io::Error::new(kind, message);

        hound::Error::IoError(error)
      })
    };

    let result = decode_file(input_file, output_file);

    if result.is_ok() {
      println!("decoded: {} -> {}", input_file, output_file);
    } else {
      return result;
    }
  }

  Ok(())
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  if let Some(ref output_file) = args.arg_output {
    let input_file = &args.arg_input[0];

    if let Err(e) = decode_file(input_file, output_file) {
      println!("{:?}", e);
    } else {
      println!("decoded: {} -> {}", input_file, output_file);
    }
  }
}
<commit_msg>Finally implement multiple FLAC file decoding<commit_after>extern crate docopt;
extern crate flac;
extern crate hound;
extern crate nom;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::Stream;

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

const USAGE: &'static str = "
Usage: decode <input> <output>
       decode <input>... <dir>
       decode --help

Options:
  -h, --help   Show this message.
";

#[derive(RustcDecodable)]
struct Arguments {
  arg_input: Vec<String>,
  arg_output: Option<String>,
  arg_dir: Option<String>,
}

fn decode_file(input_file: &str, output_file: &str)
               -> Result<(), hound::Error> {
  let mut stream = try! {
    Stream::from_file(input_file).map_err(hound::Error::IoError)
  };
  let info       = stream.info();
  let frames_len = stream.frames.len();

  let spec = hound::WavSpec {
    channels: info.channels as u16,
    sample_rate: info.sample_rate,
    bits_per_sample: info.bits_per_sample as u16,
  };

  let mut output = try!(hound::WavWriter::create(output_file, spec));

  for _ in 0..frames_len {
    if let Some(buffer) = stream.next_frame() {
      let buffer_size = buffer.len();
      let block_size  = buffer_size / 2;
      let left        = &buffer[0..block_size];
      let right       = &buffer[block_size..buffer_size];

      for i in 0..block_size {
        try!(output.write_sample(left[i]));
        try!(output.write_sample(right[i]));
      }
    } else {
      break;
    }
  }

  output.finalize()
}

fn to_output_file(buffer: &mut PathBuf, path: &Path, directory: &str)
                  -> Result<(), hound::Error> {
  buffer.push(directory);

  path.file_name().map(|name| {
    buffer.push(name);
    buffer.set_extension("wav");
  }).ok_or_else(|| {
    let kind    = io::ErrorKind::NotFound;
    let message = "no file name found";
    let error   = io::Error::new(kind, message);

    hound::Error::IoError(error)
  })
}

fn decode_all_files(input_files: &Vec<String>, directory: &str)
                    -> Result<(), hound::Error> {
  let dir_path = Path::new(directory);

  if !dir_path.exists() {
    try!(fs::create_dir(dir_path).map_err(hound::Error::IoError))
  }

  for ref input_file in input_files {
    let mut buffer = PathBuf::new();
    let path       = Path::new(input_file);

    try!(to_output_file(&mut buffer, path, directory));

    let output_file = try! {
      buffer.to_str().ok_or_else(|| {
        let kind    = io::ErrorKind::InvalidInput;
        let message = "invalid unicode with file path";
        let error   = io::Error::new(kind, message);

        hound::Error::IoError(error)
      })
    };

    let result = decode_file(input_file, output_file);

    if result.is_ok() {
      println!("decoded: {} -> {}", input_file, output_file);
    } else {
      return result;
    }
  }

  Ok(())
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  if let Some(ref output_file) = args.arg_output {
    let input_file = &args.arg_input[0];

    if let Err(e) = decode_file(input_file, output_file) {
      println!("{:?}", e);
    } else {
      println!("decoded: {} -> {}", input_file, output_file);
    }
  } else if let Some(ref directory) = args.arg_dir {
    if let Err(e) = decode_all_files(&args.arg_input, directory) {
      println!("{:?}", e);
    }
  }
}
<|endoftext|>