<commit_before>use clap::App;

fn main() {
    // This example shows how to create an application with several arguments using usage strings, which can be
    // far less verbose that shown in 01b_QuickExample.rs, but is more readable. The downside is you cannot set
    // the more advanced configuration options using this method (well...actually you can, you'll see ;) )
    //
    // The example below is functionally identical to the 01b_quick_example.rs
    //
    // Create an application with 5 possible arguments (2 auto generated) and 2 subcommands (1 auto generated)
    //    - A config file
    //        + Uses "-c filename" or "--config filename"
    //    - An output file
    //        + A positional argument (i.e. "$ myapp output_filename")
    //    - A debug flag
    //        + Uses "-d" or "--debug"
    //        + Allows multiple occurrences of such as "-dd" (for vary levels of debugging, as an example)
    //    - A help flag (automatically generated by clap)
    //        + Uses "-h" or "--help" (Only autogenerated if you do NOT specify your own "-h" or "--help")
    //    - A version flag (automatically generated by clap)
    //        + Uses "-V" or "--version" (Only autogenerated if you do NOT specify your own "-V" or "--version")
    //    - A subcommand "test" (subcommands behave like their own apps, with their own arguments
    //        + Used by "$ myapp test" with the following arguments
    //            > A list flag
    //                = Uses "-l" (usage is "$ myapp test -l"
    //            > A help flag (automatically generated by clap
    //                = Uses "-h" or "--help" (full usage "$ myapp test -h" or "$ myapp test --help")
    //            > A version flag (automatically generated by clap
    //                = Uses "-V" or "--version" (full usage "$ myapp test -V" or "$ myapp test --version")
    //    - A subcommand "help" (automatically generated by clap because we specified a subcommand of our own)
    //        + Used by "$ myapp help" (same functionality as "-h" or "--help")
    let matches = App::new("MyApp")
        .version("1.0")
        .author("Kevin K. <kbknapp@gmail.com>")
        .about("Does awesome things")
        .arg("-c, --config=[FILE] 'Sets a custom config file'")
        .arg("<output> 'Sets an optional output file'")
        .arg("-d..., --debug... 'Turn debugging information on'")
        .subcommand(
            App::new("test")
                .about("does testing things")
                .arg("-l, --list 'lists test values'"),
        )
        .get_matches();

    // You can check the value provided by positional arguments, or option arguments
    if let Some(o) = matches.value_of("output") {
        println!("Value for output: {}", o);
    }

    if let Some(c) = matches.value_of("config") {
        println!("Value for config: {}", c);
    }

    // You can see how many times a particular flag or argument occurred
    // Note, only flags can have multiple occurrences
    match matches.occurrences_of("debug") {
        0 => println!("Debug mode is off"),
        1 => println!("Debug mode is kind of on"),
        2 => println!("Debug mode is on"),
        _ => println!("Don't be crazy"),
    }

    // You can check for the existence of subcommands, and if found use their
    // matches just as you would the top level app
    if let Some(matches) = matches.subcommand_matches("test") {
        // "$ myapp test" was run
        if matches.is_present("list") {
            // "$ myapp test -l" was run
            println!("Printing testing lists...");
        } else {
            println!("Not printing testing lists...");
        }
    }

    // Continued program logic goes here...
}
<commit_msg>docs(examples): Align `quick_example`s<commit_after>use clap::App;

fn main() {
    // This example shows how to create an application with several arguments using usage strings, which can be
    // far less verbose that shown in 01b_QuickExample.rs, but is more readable. The downside is you cannot set
    // the more advanced configuration options using this method (well...actually you can, you'll see ;) )
    //
    // The example below is functionally identical to the 01b_quick_example.rs
    //
    // Create an application with 5 possible arguments (2 auto generated) and 2 subcommands (1 auto generated)
    //    - A config file
    //        + Uses "-c filename" or "--config filename"
    //    - An output file
    //        + A positional argument (i.e. "$ myapp output_filename")
    //    - A debug flag
    //        + Uses "-d" or "--debug"
    //        + Allows multiple occurrences of such as "-dd" (for vary levels of debugging, as an example)
    //    - A help flag (automatically generated by clap)
    //        + Uses "-h" or "--help" (Only autogenerated if you do NOT specify your own "-h" or "--help")
    //    - A version flag (automatically generated by clap)
    //        + Uses "-V" or "--version" (Only autogenerated if you do NOT specify your own "-V" or "--version")
    //    - A subcommand "test" (subcommands behave like their own apps, with their own arguments
    //        + Used by "$ myapp test" with the following arguments
    //            > A list flag
    //                = Uses "-l" (usage is "$ myapp test -l"
    //            > A help flag (automatically generated by clap
    //                = Uses "-h" or "--help" (full usage "$ myapp test -h" or "$ myapp test --help")
    //            > A version flag (automatically generated by clap
    //                = Uses "-V" or "--version" (full usage "$ myapp test -V" or "$ myapp test --version")
    //    - A subcommand "help" (automatically generated by clap because we specified a subcommand of our own)
    //        + Used by "$ myapp help" (same functionality as "-h" or "--help")
    let matches = App::new("MyApp")
        .version("1.0")
        .author("Kevin K. <kbknapp@gmail.com>")
        .about("Does awesome things")
        .arg("-c, --config=[FILE] 'Sets a custom config file'")
        .arg("[output] 'Sets an optional output file'")
        .arg("-d..., --debug... 'Turn debugging information on'")
        .subcommand(
            App::new("test")
                .about("does testing things")
                .arg("-l, --list 'lists test values'"),
        )
        .get_matches();

    // You can check the value provided by positional arguments, or option arguments
    if let Some(o) = matches.value_of("output") {
        println!("Value for output: {}", o);
    }

    if let Some(c) = matches.value_of("config") {
        println!("Value for config: {}", c);
    }

    // You can see how many times a particular flag or argument occurred
    // Note, only flags can have multiple occurrences
    match matches.occurrences_of("debug") {
        0 => println!("Debug mode is off"),
        1 => println!("Debug mode is kind of on"),
        2 => println!("Debug mode is on"),
        _ => println!("Don't be crazy"),
    }

    // You can check for the existence of subcommands, and if found use their
    // matches just as you would the top level app
    if let Some(matches) = matches.subcommand_matches("test") {
        // "$ myapp test" was run
        if matches.is_present("list") {
            // "$ myapp test -l" was run
            println!("Printing testing lists...");
        } else {
            println!("Not printing testing lists...");
        }
    }

    // Continued program logic goes here...
}
<|endoftext|>


<commit_before>// Rust on BareMetal - Tested with Rust 0.13.0-nightly
// rustc -O --crate-type lib -o kernel64.o --emit obj kernel64.rs
// ld -T app.ld -o kernel64.sys kernel64.o

#![no_std]
#![allow(ctypes)]
#![allow(dead_code)]
#![feature(lang_items)]
#[lang="sized"]
trait Sized {}

enum Color {
    Black       = 0,
    Blue        = 1,
    Green       = 2,
    Cyan        = 3,
    Red         = 4,
    Pink        = 5,
    Brown       = 6,
    LightGray   = 7,
    DarkGray    = 8,
    LightBlue   = 9,
    LightGreen  = 10,
    LightCyan   = 11,
    LightRed    = 12,
    LightPink   = 13,
    Yello       = 14,
    White       = 15,
}

enum Option<T> {
    None,
    Some(T)
}

struct IntRange {
    cur: int,
    max: int
}

impl IntRange {
    fn next(&mut self) -> Option<int> {
        if self.cur < self.max {
            self.cur += 1;
            Some(self.cur - 1)
        } else {
            None
        }
    }
}

fn range(lo: int, hi: int) -> IntRange {
    IntRange { cur: lo, max: hi }
}

fn clear_screen(background: Color) {
    let mut r = range(0, 80 * 25);
    loop {
        match r.next() {
            Some(x) => {
                unsafe {
                   *((0xb8000 + x * 2) as *mut u16) = (background as u16) << 12;
                }
            },
            None => {break}
        }
    }
}

#[no_mangle]
#[no_stack_check]
pub fn main() {
    clear_screen(LightBlue);
    loop {
		// Loop forever
    }
}
<commit_msg>cleanup<commit_after>// Rust on bare metal - Tested with Rust 1.0.0
// Uses Pure64 to get into a 64-bit SMP state
// rustc -O --crate-type lib -o kernel64.o --emit obj kernel64.rs
// ld -T app.ld -o kernel64.sys kernel64.o

#[no_mangle]
pub fn main() {
    clear_screen(Color::LightBlue);
    loop {
		// Loop forever
    }
}

#[derive(Copy,Clone)]
enum Color {
    Black       = 0,
    Blue        = 1,
    Green       = 2,
    Cyan        = 3,
    Red         = 4,
    Pink        = 5,
    Brown       = 6,
    LightGray   = 7,
    DarkGray    = 8,
    LightBlue   = 9,
    LightGreen  = 10,
    LightCyan   = 11,
    LightRed    = 12,
    LightPink   = 13,
    Yello       = 14,
    White       = 15,
}

fn clear_screen(background: Color) {
    for x in 0 .. 80*25 {
        unsafe {
            *((0xb8000 + x * 2) as *mut u16) = (background as u16) << 12;
        }
    }
}
<|endoftext|>


<commit_before>extern crate r2d2;
extern crate redis;
extern crate openssl;
#[macro_use] extern crate nickel;
extern crate nickel_redis;

use std::env;
use r2d2::NopErrorHandler;
use nickel::{Nickel, HttpRouter};
use nickel_redis::{RedisMiddleware, RedisRequestExtensions};

fn main() {
    let mut app = Nickel::new();

    let redis_url = env::var("DATABASE_URL").unwrap();
    let dbpool = RedisMiddleware::new(&*redis_url,
                                         5,
                                         Box::new(NopErrorHandler)).unwrap();
    app.utilize(dbpool);
    app.get("/my_counter", middleware! { |request|
        let _connection = request.redis_conn();
        println!("{:?}", _connection);

        // use connection
    });

    app.get("**", middleware! { println!("!!!") });
}
<commit_msg>Update example<commit_after>#![feature(core)]
extern crate r2d2;
extern crate redis;
#[macro_use] extern crate nickel;
extern crate nickel_redis;
extern crate core;

use std::env;
use r2d2::NopErrorHandler;
use nickel::{Nickel, HttpRouter};
use nickel_redis::{RedisMiddleware, RedisRequestExtensions};
use core::ops::Deref;

fn main() {
    let mut app = Nickel::new();

    let redis_url = env::var("DATABASE_URL").unwrap();
    let dbpool = RedisMiddleware::new(&*redis_url,
                                         5,
                                         Box::new(NopErrorHandler)).unwrap();
    app.utilize(dbpool);
    app.get("/my_counter", middleware! { |request|
        let pool_con = request.redis_conn();
        let con = pool_con.deref();

        // Use con as your connection
    });

    app.get("**", middleware! { println!("!!!") });
}
<|endoftext|>


<commit_before>use vm::{VM, Value, Int, Float, Function, Userdata, StackFrame, Data};
use typecheck::{TcType, Typed, FunctionType, unit_type_tc, bool_type_tc, int_type_tc, float_type_tc};
use compiler::CallGlobal;
use std::any::{Any, AnyRefExt};
use std::boxed::BoxAny;

pub trait VMType {
    fn vm_type<'a>(&self, vm: &'a VM) -> &'a TcType;
    fn make_type(&self, vm: &VM) -> TcType {
        self.vm_type(vm).clone()
    }
}
pub trait VMValue : VMType {
    fn push(self, stack: &mut StackFrame);
    fn from_value(value: Value) -> Option<Self>;
}
impl VMType for () {
    fn vm_type<'a>(&self, _: &'a VM) -> &'a TcType {
        &unit_type_tc
    }
}
impl VMValue for () {
    fn push(self, _: &mut StackFrame) {
    }
    fn from_value(_: Value) -> Option<()> {
        Some(())
    }
}

impl VMType for int {
    fn vm_type<'a>(&self, _: &'a VM) -> &'a TcType {
        &int_type_tc
    }
}
impl VMValue for int {
    fn push(self, stack: &mut StackFrame) {
        stack.push(Int(self));
    }
    fn from_value(value: Value) -> Option<int> {
        match value {
            Int(i) => Some(i),
            _ => None
        }
    }
}
impl VMType for f64 {
    fn vm_type<'a>(&self, _: &'a VM) -> &'a TcType {
        &float_type_tc
    }
}
impl VMValue for f64 {
    fn push(self, stack: &mut StackFrame) {
        stack.push(Float(self));
    }
    fn from_value(value: Value) -> Option<f64> {
        match value {
            Float(f) => Some(f),
            _ => None
        }
    }
}
impl VMType for bool {
    fn vm_type<'a>(&self, _: &'a VM) -> &'a TcType {
        &bool_type_tc
    }
}
impl VMValue for bool {
    fn push(self, stack: &mut StackFrame) {
        stack.push(Int(if self { 1 } else { 0 }));
    }
    fn from_value(value: Value) -> Option<bool> {
        match value {
            Int(1) => Some(true),
            Int(0) => Some(false),
            _ => None
        }
    }
}
impl <T: 'static + BoxAny + Clone> VMType for Box<T> {
    fn vm_type<'a>(&self, vm: &'a VM) -> &'a TcType {
        vm.get_type::<T>()
    }
}
impl <T: 'static + BoxAny + Clone> VMValue for Box<T> {
    fn push(self, stack: &mut StackFrame) {
        stack.push(Userdata(Data::new(self as Box<Any>)));
    }
    fn from_value(value: Value) -> Option<Box<T>> {
        match value {
            Userdata(v) => v.data.borrow().downcast_ref::<T>().map(|x| box x.clone()),
            _ => None
        }
    }
}
impl <T: 'static> VMType for *mut T {
    fn vm_type<'a>(&self, vm: &'a VM) -> &'a TcType {
        vm.get_type::<T>()
    }
}
impl <T: 'static> VMValue for *mut T {
    fn push(self, stack: &mut StackFrame) {
        stack.push(Userdata(Data::new(box self as Box<Any>)));
    }
    fn from_value(value: Value) -> Option<*mut T> {
        match value {
            Userdata(v) => v.data.borrow().downcast_ref::<*mut T>().map(|x| *x),
            _ => None
        }
    }
}

fn vm_type<'a, T: VMValue>(vm: &'a VM) -> &'a TcType {
    let t: T = unsafe { ::std::mem::uninitialized() };
    let typ = t.vm_type(vm);
    unsafe { ::std::mem::forget(t) }
    typ
}

fn make_type<'a, T: VMValue>(vm: &'a VM) -> TcType {
    let t: T = unsafe { ::std::mem::uninitialized() };
    let typ = t.make_type(vm);
    unsafe { ::std::mem::forget(t) }
    typ
}

trait Get<'a> {
    fn get_function(vm: &'a mut VM, name: &str) -> Option<Self>;
}
macro_rules! make_get(
    ($($args:ident),* -> $result:ident) => (
impl <'a, $($args : VMValue),*, $result: VMValue> Get<'a> for Callable<'a, ($($args),*), $result> {
    fn get_function(vm: &'a mut VM, name: &str) -> Option<Callable<'a, ($($args),*), $result>> {
        let value = match vm.get_global(name) {
            Some((function_ref, global)) => {
                match global.type_of() {
                    &FunctionType(ref args, ref return_type) => {
                        let mut arg_iter = args.iter();
                        let ok = $({
                            arg_iter.next().unwrap() == vm_type::<$args>(vm)
                            })&&*;
                        if arg_iter.next().is_none() && ok && **return_type == *vm_type::<$result>(vm) {
                            Some(FunctionRef { value: function_ref })
                        }
                        else {
                            None
                        }
                    }
                    _ => None
                }
            }
            None => None
        };
        match value {
            Some(value) => Some(Callable { vm: vm, value: value }),
            None => None
        }
    }
}
))

make_get!(A, B -> R)

impl <'a, T: VMValue, R: VMValue> Get<'a> for Callable<'a, (T,), R> {
    fn get_function(vm: &'a mut VM, name: &str) -> Option<Callable<'a, (T,), R>> {
        let value = match vm.get_global(name) {
            Some((function_ref, global)) => {
                match global.type_of() {
                    &FunctionType(ref args, ref return_type) => {
                        if args.len() == 1 {
                            let ok = args[0] == *vm_type::<T>(vm);
                            if ok && **return_type == *vm_type::<R>(vm) {
                                Some(FunctionRef { value: function_ref })
                            }
                            else {
                                None
                            }
                        }
                        else {
                            None
                        }
                    }
                    _ => None
                }
            }
            None => None
        };
        match value {
            Some(value) => Some(Callable { vm: vm, value: value }),
            None => None
        }
    }
}

pub struct Callable<'a, Args, R> {
    vm: &'a mut VM,
    value: FunctionRef<Args, R>
}
struct FunctionRef<Args, R> {
    value: uint
}

impl <Args, R> VMType for FunctionRef<Args, R> {
    fn vm_type<'a>(&self, vm: &'a VM) -> &'a TcType {
        vm.get_type::<|Args|:'static -> R>()
    }
}

impl <Args, R> VMValue for FunctionRef<Args, R> {
    fn push(self, stack: &mut StackFrame) {
        stack.push(Function(self.value));
    }
    fn from_value(value: Value) -> Option<FunctionRef<Args, R>> {
        match value {
            Function(i) => Some(FunctionRef { value: i }),//TODO not type safe
            _ => None
        }
    }
}

impl <'a, A: VMValue, R: VMValue> Callable<'a, (A,), R> {
    pub fn call(&mut self, a: A) -> R {
        let mut vec = Vec::new();
        {
            let mut stack = StackFrame::new(&mut vec, 0, None);
            self.value.push(&mut stack);
            a.push(&mut stack);
            self.vm.execute(stack, &[CallGlobal(1)]);
        }
        vec.pop().and_then(|value| VMValue::from_value(value))
            .expect("Wrong type")
    }
}
impl <'a, A: VMValue, B: VMValue, R: VMValue> Callable<'a, (A, B), R> {
    pub fn call2(&mut self, a: A, b: B) -> R {
        let mut vec = Vec::new();
        {
            let mut stack = StackFrame::new(&mut vec, 0, None);
            self.value.push(&mut stack);
            a.push(&mut stack);
            b.push(&mut stack);
            self.vm.execute(stack, &[CallGlobal(2)]);
        }
        vec.pop().and_then(|value| VMValue::from_value(value))
            .expect("Wrong type")
    }
}

pub fn get_function<'a, T: Get<'a>>(vm: &'a mut VM, name: &str) -> Option<T> {
    Get::get_function(vm, name)
}

trait VMFunction {
    fn unpack_and_call(mut stack: StackFrame, f: Self);
}

macro_rules! make_vm_function(
    ($($args:ident),*) => (
impl <$($args: VMValue,)* R: VMValue> VMType for fn ($($args),*) -> R {
    #[allow(non_snake_case)]
    fn vm_type<'a>(&self, vm: &'a VM) -> &'a TcType {
        vm.get_type::<fn ($($args),*) -> R>()
    }
    #[allow(non_snake_case)]
    fn make_type(&self, vm: &VM) -> TcType {
        FunctionType(vec![$(make_type::<$args>(vm)),*], box make_type::<R>(vm))
    }
}

impl <$($args : VMValue,)* R: VMValue> VMFunction for fn ($($args),*) -> R {
    #[allow(non_snake_case)]
    fn unpack_and_call(mut stack: StackFrame, f: fn ($($args),*) -> R) {
        let mut i = 0u;
        $(let $args = {
            let x = VMValue::from_value(stack[i].clone()).unwrap();
            i += 1;
            x
        });*;
        drop(i);//Avoid unused warnings
        let r = f($($args),*);
        r.push(&mut stack);
    }
}
    )
)

make_vm_function!()
make_vm_function!(A)
make_vm_function!(A, B)
make_vm_function!(A, B, C)
make_vm_function!(A, B, C, D)
make_vm_function!(A, B, C, D, E)
make_vm_function!(A, B, C, D, E, F)
make_vm_function!(A, B, C, D, E, F, G)

macro_rules! vm_function(
    ($func: expr) => ({
        fn wrapper(_: &VM, stack: StackFrame) {
            VMFunction::unpack_and_call(stack, $func)
        }
        wrapper
    })
)

macro_rules! define_function(
    ($vm: expr, $name: expr, $func: expr) => ({
        let vm = $vm;
        let (args, ret) = match $func.make_type(vm) {
            FunctionType(ref args, ref return_type) => (args.clone(), (**return_type).clone()),
            _ => fail!()
        };
        vm.extern_function($name, args, ret, vm_function!($func))
    })
)

#[cfg(test)]
mod tests {
    use super::{Get, Callable, VMType, VMFunction};

    use typecheck::FunctionType;
    use vm::{VM, load_script, StackFrame};
    use std::io::BufReader;

    #[test]
    fn call_function() {
        let s =
r"
fn add10(x: int) -> int {
    x + 10
}
fn mul(x: float, y: float) -> float {
    x * y
}
";
        let mut vm = VM::new();
        let mut buffer = BufReader::new(s.as_bytes());
        load_script(&mut vm, &mut buffer)
            .unwrap_or_else(|err| fail!("{}", err));
        {
            let mut f: Callable<(int,), int> = Get::get_function(&mut vm, "add10")
                .expect("No function");
            let result = f.call(2);
            assert_eq!(result, 12);
        }
        let mut f: Callable<(f64, f64), f64> = Get::get_function(&mut vm, "mul")
            .expect("No function");
        let result = f.call2(4., 5.);
        assert_eq!(result, 20.);
    }
    #[test]
    fn pass_userdata() {
        let s =
r"
fn id(x: Test) -> Test {
    x
}
";
        let mut vm = VM::new();
        fn test(test: *mut Test) -> bool {
            let test = unsafe { &mut *test };
            let x = test.x == 123;
            test.x *= 2;
            x
        }
        struct Test {
            x: int
        }
        vm.register_type::<Test>("Test")
            .unwrap_or_else(|_| fail!("Could not add type"));
        define_function!(&mut vm, "test", test);
        let mut buffer = BufReader::new(s.as_bytes());
        load_script(&mut vm, &mut buffer)
            .unwrap_or_else(|err| fail!("{}", err));

        let mut test = Test { x: 123 };
        {
            let mut f: Callable<(*mut Test,), *mut Test> = Get::get_function(&mut vm, "id")
                .expect("No function id");
            let result = f.call(&mut test);
            assert!(result == &mut test as *mut Test);
        }
        let mut f: Callable<(*mut Test,), bool> = Get::get_function(&mut vm, "test")
            .expect("No function test");
        let result = f.call(&mut test);
        assert!(result);
        assert_eq!(test.x, 123 * 2);
    }
}
<commit_msg>Exported the define_function macro<commit_after>#![macro_escape]
use vm::{VM, Value, Int, Float, Function, Userdata, StackFrame, Data};
use typecheck::{TcType, Typed, FunctionType, unit_type_tc, bool_type_tc, int_type_tc, float_type_tc};
use compiler::CallGlobal;
use std::any::{Any, AnyRefExt};
use std::boxed::BoxAny;

pub trait VMType {
    fn vm_type<'a>(&self, vm: &'a VM) -> &'a TcType;
    fn make_type(&self, vm: &VM) -> TcType {
        self.vm_type(vm).clone()
    }
}
pub trait VMValue : VMType {
    fn push(self, stack: &mut StackFrame);
    fn from_value(value: Value) -> Option<Self>;
}
impl VMType for () {
    fn vm_type<'a>(&self, _: &'a VM) -> &'a TcType {
        &unit_type_tc
    }
}
impl VMValue for () {
    fn push(self, _: &mut StackFrame) {
    }
    fn from_value(_: Value) -> Option<()> {
        Some(())
    }
}

impl VMType for int {
    fn vm_type<'a>(&self, _: &'a VM) -> &'a TcType {
        &int_type_tc
    }
}
impl VMValue for int {
    fn push(self, stack: &mut StackFrame) {
        stack.push(Int(self));
    }
    fn from_value(value: Value) -> Option<int> {
        match value {
            Int(i) => Some(i),
            _ => None
        }
    }
}
impl VMType for f64 {
    fn vm_type<'a>(&self, _: &'a VM) -> &'a TcType {
        &float_type_tc
    }
}
impl VMValue for f64 {
    fn push(self, stack: &mut StackFrame) {
        stack.push(Float(self));
    }
    fn from_value(value: Value) -> Option<f64> {
        match value {
            Float(f) => Some(f),
            _ => None
        }
    }
}
impl VMType for bool {
    fn vm_type<'a>(&self, _: &'a VM) -> &'a TcType {
        &bool_type_tc
    }
}
impl VMValue for bool {
    fn push(self, stack: &mut StackFrame) {
        stack.push(Int(if self { 1 } else { 0 }));
    }
    fn from_value(value: Value) -> Option<bool> {
        match value {
            Int(1) => Some(true),
            Int(0) => Some(false),
            _ => None
        }
    }
}
impl <T: 'static + BoxAny + Clone> VMType for Box<T> {
    fn vm_type<'a>(&self, vm: &'a VM) -> &'a TcType {
        vm.get_type::<T>()
    }
}
impl <T: 'static + BoxAny + Clone> VMValue for Box<T> {
    fn push(self, stack: &mut StackFrame) {
        stack.push(Userdata(Data::new(self as Box<Any>)));
    }
    fn from_value(value: Value) -> Option<Box<T>> {
        match value {
            Userdata(v) => v.data.borrow().downcast_ref::<T>().map(|x| box x.clone()),
            _ => None
        }
    }
}
impl <T: 'static> VMType for *mut T {
    fn vm_type<'a>(&self, vm: &'a VM) -> &'a TcType {
        vm.get_type::<T>()
    }
}
impl <T: 'static> VMValue for *mut T {
    fn push(self, stack: &mut StackFrame) {
        stack.push(Userdata(Data::new(box self as Box<Any>)));
    }
    fn from_value(value: Value) -> Option<*mut T> {
        match value {
            Userdata(v) => v.data.borrow().downcast_ref::<*mut T>().map(|x| *x),
            _ => None
        }
    }
}

fn vm_type<'a, T: VMValue>(vm: &'a VM) -> &'a TcType {
    let t: T = unsafe { ::std::mem::uninitialized() };
    let typ = t.vm_type(vm);
    unsafe { ::std::mem::forget(t) }
    typ
}

fn make_type<'a, T: VMValue>(vm: &'a VM) -> TcType {
    let t: T = unsafe { ::std::mem::uninitialized() };
    let typ = t.make_type(vm);
    unsafe { ::std::mem::forget(t) }
    typ
}

trait Get<'a> {
    fn get_function(vm: &'a mut VM, name: &str) -> Option<Self>;
}
macro_rules! make_get(
    ($($args:ident),* -> $result:ident) => (
impl <'a, $($args : VMValue),*, $result: VMValue> Get<'a> for Callable<'a, ($($args),*), $result> {
    fn get_function(vm: &'a mut VM, name: &str) -> Option<Callable<'a, ($($args),*), $result>> {
        let value = match vm.get_global(name) {
            Some((function_ref, global)) => {
                match global.type_of() {
                    &FunctionType(ref args, ref return_type) => {
                        let mut arg_iter = args.iter();
                        let ok = $({
                            arg_iter.next().unwrap() == vm_type::<$args>(vm)
                            })&&*;
                        if arg_iter.next().is_none() && ok && **return_type == *vm_type::<$result>(vm) {
                            Some(FunctionRef { value: function_ref })
                        }
                        else {
                            None
                        }
                    }
                    _ => None
                }
            }
            None => None
        };
        match value {
            Some(value) => Some(Callable { vm: vm, value: value }),
            None => None
        }
    }
}
))

make_get!(A, B -> R)

impl <'a, T: VMValue, R: VMValue> Get<'a> for Callable<'a, (T,), R> {
    fn get_function(vm: &'a mut VM, name: &str) -> Option<Callable<'a, (T,), R>> {
        let value = match vm.get_global(name) {
            Some((function_ref, global)) => {
                match global.type_of() {
                    &FunctionType(ref args, ref return_type) => {
                        if args.len() == 1 {
                            let ok = args[0] == *vm_type::<T>(vm);
                            if ok && **return_type == *vm_type::<R>(vm) {
                                Some(FunctionRef { value: function_ref })
                            }
                            else {
                                None
                            }
                        }
                        else {
                            None
                        }
                    }
                    _ => None
                }
            }
            None => None
        };
        match value {
            Some(value) => Some(Callable { vm: vm, value: value }),
            None => None
        }
    }
}

pub struct Callable<'a, Args, R> {
    vm: &'a mut VM,
    value: FunctionRef<Args, R>
}
struct FunctionRef<Args, R> {
    value: uint
}

impl <Args, R> VMType for FunctionRef<Args, R> {
    fn vm_type<'a>(&self, vm: &'a VM) -> &'a TcType {
        vm.get_type::<|Args|:'static -> R>()
    }
}

impl <Args, R> VMValue for FunctionRef<Args, R> {
    fn push(self, stack: &mut StackFrame) {
        stack.push(Function(self.value));
    }
    fn from_value(value: Value) -> Option<FunctionRef<Args, R>> {
        match value {
            Function(i) => Some(FunctionRef { value: i }),//TODO not type safe
            _ => None
        }
    }
}

impl <'a, A: VMValue, R: VMValue> Callable<'a, (A,), R> {
    pub fn call(&mut self, a: A) -> R {
        let mut vec = Vec::new();
        {
            let mut stack = StackFrame::new(&mut vec, 0, None);
            self.value.push(&mut stack);
            a.push(&mut stack);
            self.vm.execute(stack, &[CallGlobal(1)]);
        }
        vec.pop().and_then(|value| VMValue::from_value(value))
            .expect("Wrong type")
    }
}
impl <'a, A: VMValue, B: VMValue, R: VMValue> Callable<'a, (A, B), R> {
    pub fn call2(&mut self, a: A, b: B) -> R {
        let mut vec = Vec::new();
        {
            let mut stack = StackFrame::new(&mut vec, 0, None);
            self.value.push(&mut stack);
            a.push(&mut stack);
            b.push(&mut stack);
            self.vm.execute(stack, &[CallGlobal(2)]);
        }
        vec.pop().and_then(|value| VMValue::from_value(value))
            .expect("Wrong type")
    }
}

pub fn get_function<'a, T: Get<'a>>(vm: &'a mut VM, name: &str) -> Option<T> {
    Get::get_function(vm, name)
}

trait VMFunction {
    fn unpack_and_call(mut stack: StackFrame, f: Self);
}

macro_rules! make_vm_function(
    ($($args:ident),*) => (
impl <$($args: VMValue,)* R: VMValue> VMType for fn ($($args),*) -> R {
    #[allow(non_snake_case)]
    fn vm_type<'a>(&self, vm: &'a VM) -> &'a TcType {
        vm.get_type::<fn ($($args),*) -> R>()
    }
    #[allow(non_snake_case)]
    fn make_type(&self, vm: &VM) -> TcType {
        FunctionType(vec![$(make_type::<$args>(vm)),*], box make_type::<R>(vm))
    }
}

impl <$($args : VMValue,)* R: VMValue> VMFunction for fn ($($args),*) -> R {
    #[allow(non_snake_case)]
    fn unpack_and_call(mut stack: StackFrame, f: fn ($($args),*) -> R) {
        let mut i = 0u;
        $(let $args = {
            let x = VMValue::from_value(stack[i].clone()).unwrap();
            i += 1;
            x
        });*;
        drop(i);//Avoid unused warnings
        let r = f($($args),*);
        r.push(&mut stack);
    }
}
    )
)

make_vm_function!()
make_vm_function!(A)
make_vm_function!(A, B)
make_vm_function!(A, B, C)
make_vm_function!(A, B, C, D)
make_vm_function!(A, B, C, D, E)
make_vm_function!(A, B, C, D, E, F)
make_vm_function!(A, B, C, D, E, F, G)

macro_rules! vm_function(
    ($func: expr) => ({
        fn wrapper(_: &VM, stack: StackFrame) {
            VMFunction::unpack_and_call(stack, $func)
        }
        wrapper
    })
)

#[macro_export]
macro_rules! define_function(
    ($vm: expr, $name: expr, $func: expr) => ({
        let vm = $vm;
        let (args, ret) = match $func.make_type(vm) {
            FunctionType(ref args, ref return_type) => (args.clone(), (**return_type).clone()),
            _ => fail!()
        };
        vm.extern_function($name, args, ret, vm_function!($func))
    })
)

#[cfg(test)]
mod tests {
    use super::{Get, Callable, VMType, VMFunction};

    use typecheck::FunctionType;
    use vm::{VM, load_script, StackFrame};
    use std::io::BufReader;

    #[test]
    fn call_function() {
        let s =
r"
fn add10(x: int) -> int {
    x + 10
}
fn mul(x: float, y: float) -> float {
    x * y
}
";
        let mut vm = VM::new();
        let mut buffer = BufReader::new(s.as_bytes());
        load_script(&mut vm, &mut buffer)
            .unwrap_or_else(|err| fail!("{}", err));
        {
            let mut f: Callable<(int,), int> = Get::get_function(&mut vm, "add10")
                .expect("No function");
            let result = f.call(2);
            assert_eq!(result, 12);
        }
        let mut f: Callable<(f64, f64), f64> = Get::get_function(&mut vm, "mul")
            .expect("No function");
        let result = f.call2(4., 5.);
        assert_eq!(result, 20.);
    }
    #[test]
    fn pass_userdata() {
        let s =
r"
fn id(x: Test) -> Test {
    x
}
";
        let mut vm = VM::new();
        fn test(test: *mut Test) -> bool {
            let test = unsafe { &mut *test };
            let x = test.x == 123;
            test.x *= 2;
            x
        }
        struct Test {
            x: int
        }
        vm.register_type::<Test>("Test")
            .unwrap_or_else(|_| fail!("Could not add type"));
        define_function!(&mut vm, "test", test);
        let mut buffer = BufReader::new(s.as_bytes());
        load_script(&mut vm, &mut buffer)
            .unwrap_or_else(|err| fail!("{}", err));

        let mut test = Test { x: 123 };
        {
            let mut f: Callable<(*mut Test,), *mut Test> = Get::get_function(&mut vm, "id")
                .expect("No function id");
            let result = f.call(&mut test);
            assert!(result == &mut test as *mut Test);
        }
        let mut f: Callable<(*mut Test,), bool> = Get::get_function(&mut vm, "test")
            .expect("No function test");
        let result = f.call(&mut test);
        assert!(result);
        assert_eq!(test.x, 123 * 2);
    }
}
<|endoftext|>


<commit_before>use hyper::Client;
use hyper::header::{Headers, Accept, ContentType, qitem};
use hyper::Result as HyperResult;
use hyper::client::Response as HyperResponse;
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper::status::StatusCode;
use hyper::http::RawStatus;
use std::io::Read;
use serde_json;
use std::borrow::Cow;

use Stream;
use event::Event;
use types::Result;
use expected_version::ExpectedVersion;
use error::HesError;
use error::UserErrorKind;

header! { (ESCurrentVersion, "ES-CurrentVersion") => [String] }
header! { (ESExpectedVersion, "ES-ExpectedVersion") => [String] }
header! { (ESResolveLinkTos, "ES-ResolveLinkTos") => [bool] }

pub struct Api {}

impl Api {
    pub fn append_to_stream(&self, stream_name: &str, expected_version: ExpectedVersion, events: Vec<Event>) -> Result<()> {
        let events_as_json : Vec<String> = events.iter().map(|e| {
            format!(r#"{{
                      "eventType": "{}",
                      "eventId": "{}",
                      "data": {}
                    }}"#,
                    e.event_type.to_string(),
                    e.event_id.hyphenated().to_string(),
                    e.data.clone().unwrap()) //TODO Eliminate `clone` and deal with `unwrap`.
        }).collect::<Vec<String>>();
        let events_json: String = format!("[{}]", events_as_json.join(","));

        let client = Client::new();

        let mut headers = Headers::new();
        headers.set(
            ContentType(Mime(TopLevel::Application, SubLevel::Ext("vnd.eventstore.events+json".to_owned()), vec![]))
        );
        headers.set(ESExpectedVersion(expected_version.into()));

        let url = format!("http://127.0.0.1:2113/streams/{}", stream_name);

        let result: HyperResult<HyperResponse> = client.post(&url)
            .headers(headers)
            .body(&events_json)
            .send();

        match result {
            Ok(response) => {
                match response.status {
                    StatusCode::Created => Ok(()),
                    StatusCode::BadRequest => {
                        //      Response { status: BadRequest, headers:
                        //        Headers { Access-Control-Allow-Headers: Content-Type, X-Requested-With,
                        //                  X-Forwarded-Host, X-PINGOTHER, Authorization, ES-LongPoll,
                        //                  ES-ExpectedVersion, ES-EventId, ES-EventType, ES-RequiresMaster,
                        //                  ES-HardDelete, ES-ResolveLinkTo,
                        //                  Content-Type: text/plain; charset=utf-8,
                        //                  Content-Length: 0,
                        //                  Date: Wed, 12 Oct 2016 16:24:28 GMT,
                        //                  Connection: close,
                        //                  Access-Control-Allow-Origin: *,
                        // --->             ES-CurrentVersion: -1,
                        //                  Access-Control-Expose-Headers: Location, ES-Position, ES-CurrentVersion,
                        //                  Access-Control-Allow-Methods: POST, DELETE, GET, OPTIONS, Server: Mono-HTTPAPI/1.0, },
                        //        version: Http11,
                        //        url: "http://127.0.0.1:2113/streams/task-c0340f57a914468ea6b48f7dff3519dc",
                        // --->   status_raw: RawStatus(400, "Wrong expected EventNumber"),
                        //        message: Http11Message { is_proxied: false, method: None, stream: Wrapper { obj: Some(Reading(SizedReader(remaining=0))) } } }
                        match response.status_raw() {
                            &RawStatus(400, ref reason_phrase) => {
                                if reason_phrase == "Wrong expected EventNumber" { //TODO Introduce a constant.
                                    let expected_version = response.headers.get::<ESCurrentVersion>()
                                        .and_then(|h| Some(ExpectedVersion::from(h.to_string())));
                                    return Err(HesError::UserError(UserErrorKind::EventNumberMismatch(expected_version)))
                                } else {
                                  self.panic_showing(&response) //TODO Return 'generic' BadRequest
                                }
                            },
                            _ => self.panic_showing(&response)
                        }
                    },
                    _ => self.panic_showing(&response)
                }
            },
            Err(err) => Err(HesError::UserError(UserErrorKind::Unexpected))
        }
    }

    pub fn read_stream_events_forward(&self, stream_name: &str, start: u32, count: u32, resolve_link_tos: bool) -> Result<Stream> {
        let client = Client::new();

        let mut headers = Headers::new();
        headers.set(
            Accept(vec![
            qitem(Mime(TopLevel::Application,
                   SubLevel::Ext("vnd.eventstore.atom+json".to_owned()), vec![]))]));
        headers.set(ESResolveLinkTos(resolve_link_tos));

        let url = format!("http://127.0.0.1:2113/streams/{}/{}/forward/{}?embed=body",
                          stream_name,
                          start,
                          count);

        let mut response = try!(client.get(&url)
                                      .headers(headers)
                                      .send());
        match response.status {
            StatusCode::Ok => {
                let mut body = String::new();
                response.read_to_string(&mut body);
                let stream: Stream = serde_json::from_str(&body).unwrap();
                Ok(stream)
            },
            StatusCode::NotFound => {
                Err(HesError::UserError(UserErrorKind::StreamNotFound))
            },
            _ => {
                self.panic_showing(&response)
            }
        }
    }

    fn panic_showing(&self, response: &HyperResponse) -> ! {
        panic!("hyper::status::StatusCode {} Response: {:?}", response.status, response)
    }
}
<commit_msg>Do refactoring<commit_after>use hyper::Client;
use hyper::header::{Headers, Accept, ContentType, qitem};
use hyper::Result as HyperResult;
use hyper::client::Response as HyperResponse;
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper::status::StatusCode;
use hyper::http::RawStatus;
use std::io::Read;
use serde_json;
use std::borrow::Cow;

use Stream;
use event::Event;
use types::Result;
use expected_version::ExpectedVersion;
use error::HesError;
use error::UserErrorKind;

header! { (ESCurrentVersion, "ES-CurrentVersion") => [String] }
header! { (ESExpectedVersion, "ES-ExpectedVersion") => [String] }
header! { (ESResolveLinkTos, "ES-ResolveLinkTos") => [bool] }

const WRONG_EXPECTED_EVENT_NUMBER: &'static str = "Wrong expected EventNumber";

pub struct Api {}

impl Api {
    pub fn append_to_stream(&self, stream_name: &str, expected_version: ExpectedVersion, events: Vec<Event>) -> Result<()> {
        let events_as_json : Vec<String> = events.iter().map(|e| {
            format!(r#"{{
                      "eventType": "{}",
                      "eventId": "{}",
                      "data": {}
                    }}"#,
                    e.event_type.to_string(),
                    e.event_id.hyphenated().to_string(),
                    e.data.clone().unwrap()) //TODO Eliminate `clone` and deal with `unwrap`.
        }).collect::<Vec<String>>();
        let events_json: String = format!("[{}]", events_as_json.join(","));

        let client = Client::new();

        let mut headers = Headers::new();
        headers.set(
            ContentType(Mime(TopLevel::Application, SubLevel::Ext("vnd.eventstore.events+json".to_owned()), vec![]))
        );
        headers.set(ESExpectedVersion(expected_version.into()));

        let url = format!("http://127.0.0.1:2113/streams/{}", stream_name);

        let result: HyperResult<HyperResponse> = client.post(&url)
            .headers(headers)
            .body(&events_json)
            .send();

        match result {
            Ok(response) => {
                match response.status {
                    StatusCode::Created => Ok(()),
                    StatusCode::BadRequest => {
                        //      Response { status: BadRequest, headers:
                        //        Headers { Access-Control-Allow-Headers: Content-Type, X-Requested-With,
                        //                  X-Forwarded-Host, X-PINGOTHER, Authorization, ES-LongPoll,
                        //                  ES-ExpectedVersion, ES-EventId, ES-EventType, ES-RequiresMaster,
                        //                  ES-HardDelete, ES-ResolveLinkTo,
                        //                  Content-Type: text/plain; charset=utf-8,
                        //                  Content-Length: 0,
                        //                  Date: Wed, 12 Oct 2016 16:24:28 GMT,
                        //                  Connection: close,
                        //                  Access-Control-Allow-Origin: *,
                        // --->             ES-CurrentVersion: -1,
                        //                  Access-Control-Expose-Headers: Location, ES-Position, ES-CurrentVersion,
                        //                  Access-Control-Allow-Methods: POST, DELETE, GET, OPTIONS, Server: Mono-HTTPAPI/1.0, },
                        //        version: Http11,
                        //        url: "http://127.0.0.1:2113/streams/task-c0340f57a914468ea6b48f7dff3519dc",
                        // --->   status_raw: RawStatus(400, "Wrong expected EventNumber"),
                        //        message: Http11Message { is_proxied: false, method: None, stream: Wrapper { obj: Some(Reading(SizedReader(remaining=0))) } } }
                        match response.status_raw() {
                            &RawStatus(400, ref reason_phrase) => {
                                if reason_phrase == WRONG_EXPECTED_EVENT_NUMBER {
                                    let expected_version = response.headers.get::<ESCurrentVersion>()
                                        .and_then(|h| Some(ExpectedVersion::from(h.to_string())));
                                    return Err(HesError::UserError(UserErrorKind::EventNumberMismatch(expected_version)))
                                } else {
                                  self.panic_showing(&response) //TODO Return 'generic' BadRequest
                                }
                            },
                            _ => self.panic_showing(&response)
                        }
                    },
                    _ => self.panic_showing(&response)
                }
            },
            Err(err) => Err(HesError::UserError(UserErrorKind::Unexpected))
        }
    }

    pub fn read_stream_events_forward(&self, stream_name: &str, start: u32, count: u32, resolve_link_tos: bool) -> Result<Stream> {
        let client = Client::new();

        let mut headers = Headers::new();
        headers.set(
            Accept(vec![
            qitem(Mime(TopLevel::Application,
                   SubLevel::Ext("vnd.eventstore.atom+json".to_owned()), vec![]))]));
        headers.set(ESResolveLinkTos(resolve_link_tos));

        let url = format!("http://127.0.0.1:2113/streams/{}/{}/forward/{}?embed=body",
                          stream_name,
                          start,
                          count);

        let mut response = try!(client.get(&url)
                                      .headers(headers)
                                      .send());
        match response.status {
            StatusCode::Ok => {
                let mut body = String::new();
                response.read_to_string(&mut body);
                let stream: Stream = serde_json::from_str(&body).unwrap();
                Ok(stream)
            },
            StatusCode::NotFound => {
                Err(HesError::UserError(UserErrorKind::StreamNotFound))
            },
            _ => {
                self.panic_showing(&response)
            }
        }
    }

    fn panic_showing(&self, response: &HyperResponse) -> ! {
        panic!("hyper::status::StatusCode {} Response: {:?}", response.status, response)
    }
}
<|endoftext|>


<commit_before>use std::str;
use std::io::Read;
use std::fs::File;
use std::path::Path;
use std::sync::Arc;
use std::clone::Clone;

use hyper::status::StatusCode;
use hyper::server::{Handler, Server, Request, Response};
use mime_types::Types as MimeTypes;

pub use typemap::Key;
pub use hyper::header::Headers;
pub use hyper::header;
pub use hyper::mime;
pub use request::SapperRequest;
pub use response::SapperResponse;
pub use router_m::Router;
pub use router::SapperRouter;
pub use handler::SapperHandler;

#[derive(Clone)]
pub struct PathParams;

/// Status Codes
pub mod status {
    pub use hyper::status::StatusCode as Status;
    pub use hyper::status::StatusCode::*;
}

#[derive(Debug, PartialEq, Clone)]
pub enum Error {
    NotFound(String),
    InvalidConfig,
    InvalidRouterConfig,
    FileNotExist,
    ShouldRedirect(String),
    Break(String),
    Fatal(String),
    Custom(String),
}

pub type Result<T> = ::std::result::Result<T, Error>;

pub trait SapperModule: Sync + Send {
    fn before(&self, req: &mut SapperRequest) -> Result<()> {
        Ok(())
    }

    fn after(&self, req: &SapperRequest, res: &mut SapperResponse) -> Result<()> {
        Ok(())
    }

    fn router(&self, &mut SapperRouter) -> Result<()>;

}

pub trait SapperAppShell {
    fn before(&self, &mut SapperRequest) -> Result<()>;
    fn after(&self, &SapperRequest, &mut SapperResponse) -> Result<()>;
}

pub type GlobalInitClosure = Box<Fn(&mut SapperRequest) -> Result<()> + 'static + Send + Sync>;
pub type SapperAppShellType = Box<SapperAppShell + 'static + Send + Sync>;

pub struct SapperApp {
    pub address:        String,
    pub port:           u32,
    // for app entry, global middeware
    pub shell:          Option<Arc<SapperAppShellType>>,
    // for actually use to recognize
    pub routers:        Router,
    // do simple static file service
    pub static_service: bool,

    pub init_closure:   Option<Arc<GlobalInitClosure>>
}

impl SapperApp {
    pub fn new() -> SapperApp {
        SapperApp {
            address: String::new(),
            port: 0,
            shell: None,
            routers: Router::new(),
            static_service: true,
            init_closure: None
        }
    }

    pub fn address(&mut self, address: &str) -> &mut Self {
        self.address = address.to_owned();
        self
    }

    pub fn port(&mut self, port: u32) -> &mut Self {
        self.port = port;
        self
    }

    pub fn static_service(&mut self, open: bool) -> &mut Self {
        self.static_service = open;
        self
    }

    pub fn with_shell(&mut self, w: SapperAppShellType) -> &mut Self {
        self.shell = Some(Arc::new(w));
        self
    }

    pub fn init_global(&mut self, clos: GlobalInitClosure) -> &mut Self {
        self.init_closure = Some(Arc::new(clos));
        self
    }

    // add methods of this sapper module
    pub fn add_module(&mut self, sm: Box<SapperModule>) -> &mut Self {

        let mut router = SapperRouter::new();
        // get the sm router
        sm.router(&mut router).unwrap();
        let sm = Arc::new(sm);

        for (method, handler_vec) in router.into_router() {
            // add to wrapped router
            for &(glob, ref handler) in handler_vec.iter() {
                let method = method.clone();
                let glob = glob.clone();
                let handler = handler.clone();
                let sm = sm.clone();
                let shell = self.shell.clone();
                let init_closure = self.init_closure.clone();

                self.routers.route(method, glob, Arc::new(Box::new(move |req: &mut SapperRequest| -> Result<SapperResponse> {
                    if let Some(ref c) = init_closure {
                        c(req)?;
                    }
                    if let Some(ref shell) = shell {
                        shell.before(req)?;
                    }
                    sm.before(req)?;
                    let mut response: SapperResponse = handler.handle(req)?;
                    sm.after(req, &mut response)?;
                    if let Some(ref shell) = shell {
                        shell.after(req, &mut response)?;
                    }
                    Ok(response)
                })));
            }
        }

        self
    }

    pub fn run_http(self) {

        let addr = self.address.clone() + ":" + &self.port.to_string();
        //let self_box = Arc::new(Box::new(self));

        Server::http(&addr[..]).unwrap()
                .handle(self).unwrap();

    }
}

impl Handler for SapperApp {

    fn handle(&self, req: Request, mut res: Response) {

        let mut sreq = SapperRequest::new(Box::new(req));
        let (path, query) = sreq.uri();

        // pass req to routers, execute matched biz handler
        let response_w = self.routers.handle_method(&mut sreq, &path).unwrap();
        if response_w.is_err() {

            if self.static_service {
                match simple_file_get(&path) {
                    Ok((file_u8vec, file_mime)) => {
                        res.headers_mut().set_raw("Content-Type", vec![file_mime.as_bytes().to_vec()]);

                        return res.send(&file_u8vec[..]).unwrap();
                    },
                    Err(_) => {
                        *res.status_mut() = StatusCode::NotFound;
                        return res.send(&"".as_bytes()).unwrap();
                    }
                }
            }

            // return 404 NotFound now
            *res.status_mut() = StatusCode::NotFound;
            return res.send(&"".as_bytes()).unwrap();
        }

        let sres = response_w.unwrap();
        *res.status_mut() = sres.status();
        match sres.body() {
            &Some(ref vec) => {

                for header in sres.headers().iter() {
                    res.headers_mut()
                        .set_raw(header.name().to_owned(),
                            vec![header.value_string().as_bytes().to_vec()]);
                }

                return res.send(&vec[..]).unwrap();
            },
            &None => {
                return res.send(&"".as_bytes()).unwrap();
            }
        }

    }

}

// this is very expensive in time
// should make it as global
lazy_static! {
    static ref MTYPES: MimeTypes = { MimeTypes::new().unwrap() };
}

fn simple_file_get(path: &str) -> Result<(Vec<u8>, String)> {
    let new_path;
    if &path[(path.len()-1)..] == "/" {
        new_path = "static/".to_owned() + path + "index.html";
    }
    else {
        new_path = "static/".to_owned() + path;
    }
    //println!("file path: {}", new_path);
    match File::open(&new_path) {
        Ok(ref mut file) => {
            let mut s: Vec<u8> = vec![];
            file.read_to_end(&mut s).unwrap_or(0);

            let mt_str = MTYPES.mime_for_path(Path::new(&new_path));

            Ok((s, mt_str.to_owned()))
        },
        Err(_) => Err(Error::FileNotExist)
    }
}

<commit_msg>add description when 404.<commit_after>use std::str;
use std::io::Read;
use std::fs::File;
use std::path::Path;
use std::sync::Arc;
use std::clone::Clone;

use hyper::status::StatusCode;
use hyper::server::{Handler, Server, Request, Response};
use mime_types::Types as MimeTypes;

pub use typemap::Key;
pub use hyper::header::Headers;
pub use hyper::header;
pub use hyper::mime;
pub use request::SapperRequest;
pub use response::SapperResponse;
pub use router_m::Router;
pub use router::SapperRouter;
pub use handler::SapperHandler;

#[derive(Clone)]
pub struct PathParams;

/// Status Codes
pub mod status {
    pub use hyper::status::StatusCode as Status;
    pub use hyper::status::StatusCode::*;
}

#[derive(Debug, PartialEq, Clone)]
pub enum Error {
    NotFound(String),
    InvalidConfig,
    InvalidRouterConfig,
    FileNotExist,
    ShouldRedirect(String),
    Break(String),
    Fatal(String),
    Custom(String),
}

pub type Result<T> = ::std::result::Result<T, Error>;

pub trait SapperModule: Sync + Send {
    fn before(&self, req: &mut SapperRequest) -> Result<()> {
        Ok(())
    }

    fn after(&self, req: &SapperRequest, res: &mut SapperResponse) -> Result<()> {
        Ok(())
    }

    fn router(&self, &mut SapperRouter) -> Result<()>;

}

pub trait SapperAppShell {
    fn before(&self, &mut SapperRequest) -> Result<()>;
    fn after(&self, &SapperRequest, &mut SapperResponse) -> Result<()>;
}

pub type GlobalInitClosure = Box<Fn(&mut SapperRequest) -> Result<()> + 'static + Send + Sync>;
pub type SapperAppShellType = Box<SapperAppShell + 'static + Send + Sync>;

pub struct SapperApp {
    pub address:        String,
    pub port:           u32,
    // for app entry, global middeware
    pub shell:          Option<Arc<SapperAppShellType>>,
    // for actually use to recognize
    pub routers:        Router,
    // do simple static file service
    pub static_service: bool,

    pub init_closure:   Option<Arc<GlobalInitClosure>>
}

impl SapperApp {
    pub fn new() -> SapperApp {
        SapperApp {
            address: String::new(),
            port: 0,
            shell: None,
            routers: Router::new(),
            static_service: true,
            init_closure: None
        }
    }

    pub fn address(&mut self, address: &str) -> &mut Self {
        self.address = address.to_owned();
        self
    }

    pub fn port(&mut self, port: u32) -> &mut Self {
        self.port = port;
        self
    }

    pub fn static_service(&mut self, open: bool) -> &mut Self {
        self.static_service = open;
        self
    }

    pub fn with_shell(&mut self, w: SapperAppShellType) -> &mut Self {
        self.shell = Some(Arc::new(w));
        self
    }

    pub fn init_global(&mut self, clos: GlobalInitClosure) -> &mut Self {
        self.init_closure = Some(Arc::new(clos));
        self
    }

    // add methods of this sapper module
    pub fn add_module(&mut self, sm: Box<SapperModule>) -> &mut Self {

        let mut router = SapperRouter::new();
        // get the sm router
        sm.router(&mut router).unwrap();
        let sm = Arc::new(sm);

        for (method, handler_vec) in router.into_router() {
            // add to wrapped router
            for &(glob, ref handler) in handler_vec.iter() {
                let method = method.clone();
                let glob = glob.clone();
                let handler = handler.clone();
                let sm = sm.clone();
                let shell = self.shell.clone();
                let init_closure = self.init_closure.clone();

                self.routers.route(method, glob, Arc::new(Box::new(move |req: &mut SapperRequest| -> Result<SapperResponse> {
                    if let Some(ref c) = init_closure {
                        c(req)?;
                    }
                    if let Some(ref shell) = shell {
                        shell.before(req)?;
                    }
                    sm.before(req)?;
                    let mut response: SapperResponse = handler.handle(req)?;
                    sm.after(req, &mut response)?;
                    if let Some(ref shell) = shell {
                        shell.after(req, &mut response)?;
                    }
                    Ok(response)
                })));
            }
        }

        self
    }

    pub fn run_http(self) {

        let addr = self.address.clone() + ":" + &self.port.to_string();
        //let self_box = Arc::new(Box::new(self));

        Server::http(&addr[..]).unwrap()
                .handle(self).unwrap();

    }
}

impl Handler for SapperApp {

    fn handle(&self, req: Request, mut res: Response) {

        let mut sreq = SapperRequest::new(Box::new(req));
        let (path, query) = sreq.uri();

        // pass req to routers, execute matched biz handler
        let response_w = self.routers.handle_method(&mut sreq, &path).unwrap();
        if response_w.is_err() {

            if self.static_service {
                match simple_file_get(&path) {
                    Ok((file_u8vec, file_mime)) => {
                        res.headers_mut().set_raw("Content-Type", vec![file_mime.as_bytes().to_vec()]);

                        return res.send(&file_u8vec[..]).unwrap();
                    },
                    Err(_) => {
                        *res.status_mut() = StatusCode::NotFound;
                        return res.send(&"404 Not Found".as_bytes()).unwrap();
                    }
                }
            }

            // return 404 NotFound now
            *res.status_mut() = StatusCode::NotFound;
            return res.send(&"404 Not Found".as_bytes()).unwrap();
        }

        let sres = response_w.unwrap();
        *res.status_mut() = sres.status();
        match sres.body() {
            &Some(ref vec) => {

                for header in sres.headers().iter() {
                    res.headers_mut()
                        .set_raw(header.name().to_owned(),
                            vec![header.value_string().as_bytes().to_vec()]);
                }

                return res.send(&vec[..]).unwrap();
            },
            &None => {
                return res.send(&"".as_bytes()).unwrap();
            }
        }

    }

}

// this is very expensive in time
// should make it as global
lazy_static! {
    static ref MTYPES: MimeTypes = { MimeTypes::new().unwrap() };
}

fn simple_file_get(path: &str) -> Result<(Vec<u8>, String)> {
    let new_path;
    if &path[(path.len()-1)..] == "/" {
        new_path = "static/".to_owned() + path + "index.html";
    }
    else {
        new_path = "static/".to_owned() + path;
    }
    //println!("file path: {}", new_path);
    match File::open(&new_path) {
        Ok(ref mut file) => {
            let mut s: Vec<u8> = vec![];
            file.read_to_end(&mut s).unwrap_or(0);

            let mt_str = MTYPES.mime_for_path(Path::new(&new_path));

            Ok((s, mt_str.to_owned()))
        },
        Err(_) => Err(Error::FileNotExist)
    }
}

<|endoftext|>


<commit_before>use std::thread;
use std::time::Duration;
use time::precise_time_ns;

use bootstrap::{Action, Context, Key, Keyboard, Mouse, MouseButton, MouseMove, Scroll, Window};
use camera::{Camera, Freefly};
use transform::Translation;

/// All common stuff goes here.
pub struct App {
  /// Some kind of epoch start the application started at.
  start_time: u64,
  /// Keyboard receiver.
  kbd: Keyboard,
  /// Mouse receiver.
  mouse: Mouse,
  /// Cursor receiver.
  cursor: MouseMove,
  /// Scroll receiver.
  scroll: Scroll,
  /// Window.
  window: Window,
  /// Last known cursor position.
  last_cursor: [f64; 2],
  /// Is the mouse’s left button pressed down?
  left_down: bool,
  /// Is the mouse’s right button pressed down?
  right_down: bool,
}

impl App {
  pub fn init(kbd: Keyboard, mouse: Mouse, cursor: MouseMove, scroll: Scroll, window: Window) -> Self {
    App {
      start_time: precise_time_ns(),
      kbd: kbd,
      mouse: mouse,
      cursor: cursor,
      scroll: scroll,
      window: window,
      last_cursor: [0., 0.],
      left_down: false,
      right_down: false,
    }
  }

  pub fn time(&self) -> f32 {
    (precise_time_ns() - self.start_time) as f32 * 1e-9
  }

  pub fn handle_events(&mut self, camera: &mut Camera<Freefly>) -> bool {
    while let Ok((key, action)) = self.kbd.try_recv() {
      if action == Action::Release && key == Key::Escape{
        return false;
      } else {
        match key {
          Key::W => camera.mv(Translation::new(0., 0., 1.)),
          Key::S => camera.mv(Translation::new(0., 0., -1.)),
          Key::A => camera.mv(Translation::new(1., 0., 0.)),
          Key::D => camera.mv(Translation::new(-1., 0., 0.)),
          Key::Q => camera.mv(Translation::new(0., -1., 0.)),
          Key::E => camera.mv(Translation::new(0., 1., 0.)),
          _ => {}
        }
      }
    }

    while let Ok((button, action)) = self.mouse.try_recv() {
      match (button, action) {
        (MouseButton::Button1, Action::Press) => {
          self.left_down = true;
        },
        (MouseButton::Button1, Action::Release) => {
          self.left_down = false;
        },
        (MouseButton::Button2, Action::Press) => {
          self.right_down = true;
        },
        (MouseButton::Button2, Action::Release) => {
          self.right_down = false;
        },
        _ => {}
      }
    }

    while let Ok(xy) = self.cursor.try_recv() {
      if self.left_down {
        let (dx, dy) = (xy[0] - self.last_cursor[0], xy[1] - self.last_cursor[1]);
        camera.look_around(Translation::new(dy as f32, dx as f32, 0.));
      } else if self.right_down {
        let (dx, _) = (xy[0] - self.last_cursor[0], xy[1] - self.last_cursor[1]);
        camera.look_around(Translation::new(0., 0., dx as f32));
      }

      self.last_cursor = xy;
    }

    true
  }

  pub fn step<R>(&mut self, mut draw_frame: R) -> bool where R: FnMut(f32) {
    let loop_start_time = precise_time_ns();

    if self.window.should_close() {
      return false;
    }

    let t = self.time();

    draw_frame(t);

    self.window.swap_buffers();

    // wait for next frame according to the wished FPS
    let fps = 60.;
    let elapsed_time_ms = ((precise_time_ns() - loop_start_time) as f64 * 1e-6) as i64;
    let sleep_time_ms = (1. / fps * 1e3) as i64 - elapsed_time_ms;

    if sleep_time_ms > 0 {
      thread::sleep(Duration::from_millis(sleep_time_ms as u64));
    }

    true
  }
}
<commit_msg>Added fps to step.<commit_after>use std::thread;
use std::time::Duration;
use time::precise_time_ns;

use bootstrap::{Action, Context, Key, Keyboard, Mouse, MouseButton, MouseMove, Scroll, Window};
use camera::{Camera, Freefly};
use transform::Translation;

/// All common stuff goes here.
pub struct App {
  /// Some kind of epoch start the application started at.
  start_time: u64,
  /// Keyboard receiver.
  kbd: Keyboard,
  /// Mouse receiver.
  mouse: Mouse,
  /// Cursor receiver.
  cursor: MouseMove,
  /// Scroll receiver.
  scroll: Scroll,
  /// Window.
  window: Window,
  /// Last known cursor position.
  last_cursor: [f64; 2],
  /// Is the mouse’s left button pressed down?
  left_down: bool,
  /// Is the mouse’s right button pressed down?
  right_down: bool,
}

impl App {
  pub fn init(kbd: Keyboard, mouse: Mouse, cursor: MouseMove, scroll: Scroll, window: Window) -> Self {
    App {
      start_time: precise_time_ns(),
      kbd: kbd,
      mouse: mouse,
      cursor: cursor,
      scroll: scroll,
      window: window,
      last_cursor: [0., 0.],
      left_down: false,
      right_down: false,
    }
  }

  pub fn time(&self) -> f32 {
    (precise_time_ns() - self.start_time) as f32 * 1e-9
  }

  pub fn handle_events(&mut self, camera: &mut Camera<Freefly>) -> bool {
    while let Ok((key, action)) = self.kbd.try_recv() {
      if action == Action::Release && key == Key::Escape{
        return false;
      } else {
        match key {
          Key::W => camera.mv(Translation::new(0., 0., 1.)),
          Key::S => camera.mv(Translation::new(0., 0., -1.)),
          Key::A => camera.mv(Translation::new(1., 0., 0.)),
          Key::D => camera.mv(Translation::new(-1., 0., 0.)),
          Key::Q => camera.mv(Translation::new(0., -1., 0.)),
          Key::E => camera.mv(Translation::new(0., 1., 0.)),
          _ => {}
        }
      }
    }

    while let Ok((button, action)) = self.mouse.try_recv() {
      match (button, action) {
        (MouseButton::Button1, Action::Press) => {
          self.left_down = true;
        },
        (MouseButton::Button1, Action::Release) => {
          self.left_down = false;
        },
        (MouseButton::Button2, Action::Press) => {
          self.right_down = true;
        },
        (MouseButton::Button2, Action::Release) => {
          self.right_down = false;
        },
        _ => {}
      }
    }

    while let Ok(xy) = self.cursor.try_recv() {
      if self.left_down {
        let (dx, dy) = (xy[0] - self.last_cursor[0], xy[1] - self.last_cursor[1]);
        camera.look_around(Translation::new(dy as f32, dx as f32, 0.));
      } else if self.right_down {
        let (dx, _) = (xy[0] - self.last_cursor[0], xy[1] - self.last_cursor[1]);
        camera.look_around(Translation::new(0., 0., dx as f32));
      }

      self.last_cursor = xy;
    }

    true
  }

  pub fn step<R>(&mut self, fps: Option<u32>, mut draw_frame: R) -> bool where R: FnMut(f32) {
    let loop_start_time = precise_time_ns();

    if self.window.should_close() {
      return false;
    }

    let t = self.time();

    draw_frame(t);

    self.window.swap_buffers();

    // wait for next frame according to the wished FPS
    if let Some(fps) = fps {
      let fps = fps as f32;
      let elapsed_time_ms = ((precise_time_ns() - loop_start_time) as f64 * 1e-6) as i64;
      let sleep_time_ms = (1. / fps * 1e3) as i64 - elapsed_time_ms;

      if sleep_time_ms > 0 {
        thread::sleep(Duration::from_millis(sleep_time_ms as u64));
      }
    }

    true
  }
}
<|endoftext|>


<commit_before>use std::error::FromError;
use std::time::Duration;

use nanomsg::{Endpoint, PollRequest, Protocol, Socket, NanoErrorKind};
use protobuf::{self, Message};
use rustc_serialize::json;

use block::HashedBlockExt;
use crypto::HashDigest;
use error::{SimplesResult};
use service::{HeadBlockPubService, RpcService, StakerService};
use simples_pb::{
    self, RpcRequest, RpcRequest_Method, RpcResponse, RpcResponse_Status,
    PublishTransactionRequest, PublishTransactionResponse,
    PublishBlockRequest, PublishBlockResponse, HashedBlock,
    Wallet};
use staking::{BlockTemplate, Staker, STAKING_INTERVAL};
use wallet::WalletExt;

pub struct Client {
    pub endpoint_str: String,
    endpoint: Endpoint,
    socket: Socket
}

impl Client {
    pub fn new(endpoint_str: &str) -> SimplesResult<Client> {
        let mut socket = try!(Socket::new(Protocol::Req));
        Ok(Client {
            endpoint_str: String::from_str(endpoint_str),
            endpoint: try!(socket.connect(endpoint_str)),
            socket: socket
        })
    }

    fn dispatch(&mut self, request: RpcRequest) -> SimplesResult<RpcResponse> {
        let request_bytes = try!(request.write_to_bytes());
        try!(self.socket.write_all(&request_bytes[]));

        let response_bytes = try!(self.socket.read_to_end());
        Ok(try!(protobuf::parse_from_bytes(&response_bytes[])))
    }
}

impl Drop for Client {
    fn drop(&mut self) { self.endpoint.shutdown().unwrap(); }
}

impl RpcService for Client {
    fn pub_block(&mut self, request: PublishBlockRequest) ->
        SimplesResult<PublishBlockResponse>
    {
        let mut wrapped_request = RpcRequest::new();
        wrapped_request.set_method(RpcRequest_Method::PUBLISH_BLOCK);
        wrapped_request.set_pub_block(request);
        self.dispatch(wrapped_request)
            .map(|mut response| response.take_pub_block())
    }

    fn pub_transaction(&mut self, request: PublishTransactionRequest) ->
        SimplesResult<PublishTransactionResponse>
    {
        let mut wrapped_request = RpcRequest::new();
        wrapped_request.set_method(RpcRequest_Method::PUBLISH_TRANSACTION);
        wrapped_request.set_pub_transaction(request);
        self.dispatch(wrapped_request)
            .map(|mut response| response.take_pub_transaction())
    }
}

pub struct Application<Service: RpcService + StakerService + HeadBlockPubService> {
    pub endpoint: String,
    peers: Vec<Client>,
    service: Service,
    staker: Staker,
    sub_head_socket: Socket,
    sub_head_endpoint: Endpoint
}

impl<Service: RpcService + StakerService + HeadBlockPubService>
    Application<Service> {
    pub fn new(endpoint: &str, service: Service, peers: Vec<String>,
               staking_keys: Wallet)
               -> SimplesResult<Application<Service>>
    {
        let mut sub_head_socket = try!(Socket::new(Protocol::Sub));
        try!(sub_head_socket.subscribe(""));
        let sub_head_endpoint = try!(
            sub_head_socket.connect(service.get_pub_endpoint()));
        let staker = Staker::new(
            try!(HashDigest::from_bytes(service.current_head_block().get_hash())),
            service.current_head_block().get_block().get_timestamp());

        let mut peer_clients = Vec::<Client>::new();
        for endpoint in peers.iter() {
            peer_clients.push(try!(Client::new(endpoint)));
        }

        Ok(Application {
            endpoint: String::from_str(endpoint),
            peers: peer_clients,
            service: service,
            staker: staker,
            sub_head_socket: sub_head_socket,
            sub_head_endpoint: sub_head_endpoint
        })
    }

    fn dispatch(&mut self, mut request: RpcRequest) -> RpcResponse {
        let mut response = RpcResponse::new();
        match request.get_method() {
            RpcRequest_Method::INVALID => {
                println!("Peer tried to call invalid method.");
                response.set_status(RpcResponse_Status::INVALID_METHOD);
                response
            },
            RpcRequest_Method::PUBLISH_TRANSACTION => {
                response.set_status(RpcResponse_Status::OK);
                response.set_pub_transaction(
                    self.service.pub_transaction(
                        request.take_pub_transaction()).unwrap());
                response
            },
            RpcRequest_Method::PUBLISH_BLOCK => {
                response.set_status(RpcResponse_Status::OK);
                response.set_pub_block(
                    self.service.pub_block(request.take_pub_block()).unwrap());
                response
            }
        }
    }

    fn handle_raw_request(&mut self, raw_request: &[u8]) -> RpcResponse {
        match protobuf::parse_from_bytes(&raw_request[]) {
            Ok(request) => self.dispatch(request),
            Err(err) => {
                println!("[app loop] Failed to parse protobuf '{:?}'.", err);
                let mut response = simples_pb::RpcResponse::new();
                response.set_status(
                    simples_pb::RpcResponse_Status::INVALID_MESSAGE);
                response
            }
        }
    }

    pub fn run(&mut self) -> SimplesResult<()> {
        let mut rpc_socket = try!(Socket::new(Protocol::Rep));
        let mut rpc_endpoint = try!(rpc_socket.bind(&self.endpoint[]));
        let mut poll_fds = [rpc_socket.new_pollfd(true, false),
                            self.sub_head_socket.new_pollfd(true, false)];
        let mut poll_request = PollRequest::new(&mut poll_fds[]);

        println!("[app loop] RPC service is running at {}", self.endpoint);
        loop {
            let poll_result = Socket::poll(
                &mut poll_request, &Duration::seconds(STAKING_INTERVAL));
            if poll_result.is_err() {
                let err = poll_result.err().unwrap();
                if err.kind == NanoErrorKind::Timeout {
                    println!("Rpc timeout.");
                    self.handle_timeout();
                } else {
                    println!("[app loop] Failed to read in request '{}'. Exiting.",
                             err);
                    return Err(FromError::from_error(err));
                }
            }
            if poll_request.get_fds()[0].can_read() { // Rpc Request
                match rpc_socket.read_to_end() {
                    Ok(request) => {
                        let response = self.handle_raw_request(&request[]);
                        let response_bytes = response.write_to_bytes().unwrap();
                        let write_result = rpc_socket.write_all(&response_bytes[]);
                        if write_result.is_err() {
                            let err = write_result.err().unwrap();
                            println!("[app loop] Failed to send response '{}'. Exiting.",
                                     err);
                        }
                    },
                    Err(err) => {
                        println!(
                            "[app loop] Failed to read in request '{}'. Exiting.",
                            err);
                        return Err(FromError::from_error(err));
                    }
                }
            }
            if poll_request.get_fds()[1].can_read() { // New head block
                match self.sub_head_socket.read_to_end() {
                    Ok(msg) => {
                        self.handle_new_head_block(
                            try!(protobuf::parse_from_bytes(&msg[])));
                    },
                    Err(err) => {
                        println!(
                            "[app loop] Failed to read in published new block '{}'.",
                            err);
                        return Err(FromError::from_error(err));
                    }
                };
            }
        } // loop
        try!(rpc_endpoint.shutdown());
    }

    fn handle_timeout(&mut self) -> SimplesResult<()> {
        match self.staker.stake_interval(STAKING_INTERVAL) {
            Some(template) => self.service.on_successful_stake(template),
            None => Ok(())
        }
    }

    fn handle_new_head_block(&mut self, new_head: HashedBlock)
                             -> SimplesResult<()>
    {
        println!("Sub-ed new block!");
        self.staker.set_head_block(
            try!(HashDigest::from_bytes(new_head.get_hash())),
            new_head.get_block().get_timestamp());

        for peer_index in range(0, self.peers.len()) {
            let mut request = PublishBlockRequest::new();
            request.set_block(new_head.clone());
            let response = self.peers[peer_index].pub_block(request);
            if response.is_err() {
                println!("Could not pub_block to peer \"{}\":P{}",
                         self.peers[peer_index].endpoint_str,
                         response.as_ref().err().unwrap());
            }
            println!("pub_block: got status {:?}", response.unwrap().get_status());
        }
        Ok(())
    }
}

#[unsafe_destructor]
impl<Service: RpcService + StakerService + HeadBlockPubService> Drop
    for Application<Service> {
    fn drop(&mut self) { self.sub_head_endpoint.shutdown().unwrap(); }
}

// use std::old_io::timer::sleep;
// use std::time::duration::Duration;
// use std::thread::Thread;

// #[test]
// fn test_receiver() {
//     let server = Thread::scoped(move || {
//         // let mut socket1 = Socket::new(Protocol::Rep).unwrap();
//         // let mut endpoint1 = socket1.bind("inproc://mata1").unwrap();
//         let mut socket2 = Socket::new(Protocol::Pull).unwrap();
//         let mut endpoint2 = socket2.bind("inproc://mata").unwrap();

//         let mut socket_fds = vec![socket2.new_pollfd(true, false)];
//             // socket1.new_pollfd(true, false), socket2.new_pollfd(true, false)];
//         let mut poll_request = PollRequest::new(&mut socket_fds[]);

//         loop {
//             let poll_result = Socket::poll(&mut poll_request, &Duration::milliseconds(50));
//             if poll_result.is_err() {
//                 if poll_result.err().unwrap().kind == NanoErrorKind::Timeout {
//                     println!("Timeout, re-listening");
//                     continue;
//                 } else {
//                     println!("[app  Failed to read in request '{}'. Exiting.",
//                              poll_result.err().unwrap());
//                     break;
//                 }
//             }
//             println!("Something is ready!");
//             if poll_request.get_fds()[0].can_read() {
//                 println!("server: received {}",
//                          String::from_utf8(socket2.read_to_end().unwrap()).unwrap());
//                 // socket2.write_all(b"pong").unwrap();
//             }
//             // if poll_request.get_fds()[1].can_read() {
//             //     println!("mata2: received {}",
//             //              String::from_utf8(socket2.read_to_end().unwrap()).unwrap());
//             // }
//         }
//     });

//     let client1 = Thread::scoped(move || {
//         let mut socket = Socket::new(Protocol::Req).unwrap();
//         let mut endpoint = socket.connect("inproc://mata").unwrap();

//         for _ in range(0, 10) {
//             sleep(Duration::seconds(2));
//             println!("client1: sending request to mata1");
//             socket.write_all(b"client1");
//             println!("client1: received {}",
//                      String::from_utf8(socket.read_to_end().unwrap()).unwrap());
//         }
//     });

//     let client2 = Thread::scoped(move || {
//         let mut socket = Socket::new(Protocol::Push).unwrap();
//         let mut endpoint = socket.connect("inproc://mata").unwrap();

//         for _ in range(0, 10) {
//             sleep(Duration::seconds(1));
//             println!("client2: sending request to mata2");
//             socket.write_all(b"client2");
//         }
//     });
//     sleep(Duration::seconds(40))
// }
<commit_msg>Added continue as sometimes nanomsg seems to hang on can_read after timeout (?)<commit_after>use std::error::FromError;
use std::time::Duration;

use nanomsg::{Endpoint, PollRequest, Protocol, Socket, NanoErrorKind};
use protobuf::{self, Message};
use rustc_serialize::json;

use block::HashedBlockExt;
use crypto::HashDigest;
use error::{SimplesResult};
use service::{HeadBlockPubService, RpcService, StakerService};
use simples_pb::{
    self, RpcRequest, RpcRequest_Method, RpcResponse, RpcResponse_Status,
    PublishTransactionRequest, PublishTransactionResponse,
    PublishBlockRequest, PublishBlockResponse, HashedBlock,
    Wallet};
use staking::{BlockTemplate, Staker, STAKING_INTERVAL};
use wallet::WalletExt;

pub struct Client {
    pub endpoint_str: String,
    endpoint: Endpoint,
    socket: Socket
}

impl Client {
    pub fn new(endpoint_str: &str) -> SimplesResult<Client> {
        let mut socket = try!(Socket::new(Protocol::Req));
        Ok(Client {
            endpoint_str: String::from_str(endpoint_str),
            endpoint: try!(socket.connect(endpoint_str)),
            socket: socket
        })
    }

    fn dispatch(&mut self, request: RpcRequest) -> SimplesResult<RpcResponse> {
        let request_bytes = try!(request.write_to_bytes());
        try!(self.socket.write_all(&request_bytes[]));

        let response_bytes = try!(self.socket.read_to_end());
        Ok(try!(protobuf::parse_from_bytes(&response_bytes[])))
    }
}

impl Drop for Client {
    fn drop(&mut self) { self.endpoint.shutdown().unwrap(); }
}

impl RpcService for Client {
    fn pub_block(&mut self, request: PublishBlockRequest) ->
        SimplesResult<PublishBlockResponse>
    {
        let mut wrapped_request = RpcRequest::new();
        wrapped_request.set_method(RpcRequest_Method::PUBLISH_BLOCK);
        wrapped_request.set_pub_block(request);
        self.dispatch(wrapped_request)
            .map(|mut response| response.take_pub_block())
    }

    fn pub_transaction(&mut self, request: PublishTransactionRequest) ->
        SimplesResult<PublishTransactionResponse>
    {
        let mut wrapped_request = RpcRequest::new();
        wrapped_request.set_method(RpcRequest_Method::PUBLISH_TRANSACTION);
        wrapped_request.set_pub_transaction(request);
        self.dispatch(wrapped_request)
            .map(|mut response| response.take_pub_transaction())
    }
}

pub struct Application<Service: RpcService + StakerService + HeadBlockPubService> {
    pub endpoint: String,
    peers: Vec<Client>,
    service: Service,
    staker: Staker,
    sub_head_socket: Socket,
    sub_head_endpoint: Endpoint
}

impl<Service: RpcService + StakerService + HeadBlockPubService>
    Application<Service> {
    pub fn new(endpoint: &str, service: Service, peers: Vec<String>,
               staking_keys: Wallet)
               -> SimplesResult<Application<Service>>
    {
        let mut sub_head_socket = try!(Socket::new(Protocol::Sub));
        try!(sub_head_socket.subscribe(""));
        let sub_head_endpoint = try!(
            sub_head_socket.connect(service.get_pub_endpoint()));
        let staker = Staker::new(
            try!(HashDigest::from_bytes(service.current_head_block().get_hash())),
            service.current_head_block().get_block().get_timestamp());

        let mut peer_clients = Vec::<Client>::new();
        for endpoint in peers.iter() {
            peer_clients.push(try!(Client::new(endpoint)));
        }

        Ok(Application {
            endpoint: String::from_str(endpoint),
            peers: peer_clients,
            service: service,
            staker: staker,
            sub_head_socket: sub_head_socket,
            sub_head_endpoint: sub_head_endpoint
        })
    }

    fn dispatch(&mut self, mut request: RpcRequest) -> RpcResponse {
        let mut response = RpcResponse::new();
        match request.get_method() {
            RpcRequest_Method::INVALID => {
                println!("Peer tried to call invalid method.");
                response.set_status(RpcResponse_Status::INVALID_METHOD);
                response
            },
            RpcRequest_Method::PUBLISH_TRANSACTION => {
                response.set_status(RpcResponse_Status::OK);
                response.set_pub_transaction(
                    self.service.pub_transaction(
                        request.take_pub_transaction()).unwrap());
                response
            },
            RpcRequest_Method::PUBLISH_BLOCK => {
                response.set_status(RpcResponse_Status::OK);
                response.set_pub_block(
                    self.service.pub_block(request.take_pub_block()).unwrap());
                response
            }
        }
    }

    fn handle_raw_request(&mut self, raw_request: &[u8]) -> RpcResponse {
        match protobuf::parse_from_bytes(&raw_request[]) {
            Ok(request) => self.dispatch(request),
            Err(err) => {
                println!("[app loop] Failed to parse protobuf '{:?}'.", err);
                let mut response = simples_pb::RpcResponse::new();
                response.set_status(
                    simples_pb::RpcResponse_Status::INVALID_MESSAGE);
                response
            }
        }
    }

    pub fn run(&mut self) -> SimplesResult<()> {
        let mut rpc_socket = try!(Socket::new(Protocol::Rep));
        let mut rpc_endpoint = try!(rpc_socket.bind(&self.endpoint[]));
        let mut poll_fds = [rpc_socket.new_pollfd(true, false),
                            self.sub_head_socket.new_pollfd(true, false)];
        let mut poll_request = PollRequest::new(&mut poll_fds[]);

        println!("[app loop] RPC service is running at {}", self.endpoint);
        loop {
            let poll_result = Socket::poll(
                &mut poll_request, &Duration::seconds(STAKING_INTERVAL));
            if poll_result.is_err() {
                let err = poll_result.err().unwrap();
                if err.kind == NanoErrorKind::Timeout {
                    try!(self.handle_timeout());
                    continue;
                } else {
                    println!("[app loop] Failed to read in request '{}'. Exiting.",
                             err);
                    return Err(FromError::from_error(err));
                }
            }
            if poll_request.get_fds()[0].can_read() { // Rpc Request
                match rpc_socket.read_to_end() {
                    Ok(request) => {
                        let response = self.handle_raw_request(&request[]);
                        let response_bytes = response.write_to_bytes().unwrap();
                        let write_result = rpc_socket.write_all(&response_bytes[]);
                        if write_result.is_err() {
                            let err = write_result.err().unwrap();
                            println!("[app loop] Failed to send response '{}'. Exiting.",
                                     err);
                        }
                    },
                    Err(err) => {
                        println!(
                            "[app loop] Failed to read in request '{}'. Exiting.",
                            err);
                        return Err(FromError::from_error(err));
                    }
                }
            }
            if poll_request.get_fds()[1].can_read() { // New head block
                match self.sub_head_socket.read_to_end() {
                    Ok(msg) => {
                        self.handle_new_head_block(
                            try!(protobuf::parse_from_bytes(&msg[])));
                    },
                    Err(err) => {
                        println!(
                            "[app loop] Failed to read in published new block '{}'.",
                            err);
                        return Err(FromError::from_error(err));
                    }
                };
            }
        } // loop
        try!(rpc_endpoint.shutdown());
    }

    fn handle_timeout(&mut self) -> SimplesResult<()> {
        match self.staker.stake_interval(STAKING_INTERVAL) {
            Some(template) => self.service.on_successful_stake(template),
            None => Ok(())
        }
    }

    fn handle_new_head_block(&mut self, new_head: HashedBlock)
                             -> SimplesResult<()>
    {
        println!("Sub-ed new block!");
        self.staker.set_head_block(
            try!(HashDigest::from_bytes(new_head.get_hash())),
            new_head.get_block().get_timestamp());

        for peer_index in range(0, self.peers.len()) {
            let mut request = PublishBlockRequest::new();
            request.set_block(new_head.clone());
            let response = self.peers[peer_index].pub_block(request);
            if response.is_err() {
                println!("Could not pub_block to peer \"{}\":P{}",
                         self.peers[peer_index].endpoint_str,
                         response.as_ref().err().unwrap());
            }
            println!("pub_block: got status {:?}", response.unwrap().get_status());
        }
        Ok(())
    }
}

#[unsafe_destructor]
impl<Service: RpcService + StakerService + HeadBlockPubService> Drop
    for Application<Service> {
    fn drop(&mut self) { self.sub_head_endpoint.shutdown().unwrap(); }
}

// use std::old_io::timer::sleep;
// use std::time::duration::Duration;
// use std::thread::Thread;

// #[test]
// fn test_receiver() {
//     let server = Thread::scoped(move || {
//         // let mut socket1 = Socket::new(Protocol::Rep).unwrap();
//         // let mut endpoint1 = socket1.bind("inproc://mata1").unwrap();
//         let mut socket2 = Socket::new(Protocol::Pull).unwrap();
//         let mut endpoint2 = socket2.bind("inproc://mata").unwrap();

//         let mut socket_fds = vec![socket2.new_pollfd(true, false)];
//             // socket1.new_pollfd(true, false), socket2.new_pollfd(true, false)];
//         let mut poll_request = PollRequest::new(&mut socket_fds[]);

//         loop {
//             let poll_result = Socket::poll(&mut poll_request, &Duration::milliseconds(50));
//             if poll_result.is_err() {
//                 if poll_result.err().unwrap().kind == NanoErrorKind::Timeout {
//                     println!("Timeout, re-listening");
//                     continue;
//                 } else {
//                     println!("[app  Failed to read in request '{}'. Exiting.",
//                              poll_result.err().unwrap());
//                     break;
//                 }
//             }
//             println!("Something is ready!");
//             if poll_request.get_fds()[0].can_read() {
//                 println!("server: received {}",
//                          String::from_utf8(socket2.read_to_end().unwrap()).unwrap());
//                 // socket2.write_all(b"pong").unwrap();
//             }
//             // if poll_request.get_fds()[1].can_read() {
//             //     println!("mata2: received {}",
//             //              String::from_utf8(socket2.read_to_end().unwrap()).unwrap());
//             // }
//         }
//     });

//     let client1 = Thread::scoped(move || {
//         let mut socket = Socket::new(Protocol::Req).unwrap();
//         let mut endpoint = socket.connect("inproc://mata").unwrap();

//         for _ in range(0, 10) {
//             sleep(Duration::seconds(2));
//             println!("client1: sending request to mata1");
//             socket.write_all(b"client1");
//             println!("client1: received {}",
//                      String::from_utf8(socket.read_to_end().unwrap()).unwrap());
//         }
//     });

//     let client2 = Thread::scoped(move || {
//         let mut socket = Socket::new(Protocol::Push).unwrap();
//         let mut endpoint = socket.connect("inproc://mata").unwrap();

//         for _ in range(0, 10) {
//             sleep(Duration::seconds(1));
//             println!("client2: sending request to mata2");
//             socket.write_all(b"client2");
//         }
//     });
//     sleep(Duration::seconds(40))
// }
<|endoftext|>