<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use appkit::NSRect;

use std::libc;
use std::libc::c_long;

pub type id = libc::intptr_t;
pub type Class = libc::intptr_t;
pub type IMP = extern "C" fn(id, SEL) -> id;
pub type SEL = libc::intptr_t;
pub type Ivar = libc::intptr_t;

pub static NIL : id = 0 as id;

extern {
    pub fn class_addMethod(cls: Class, name: SEL, imp: IMP, types: *libc::c_char) -> bool;
    pub fn class_addIvar(cls : Class,
                         name : *libc::c_char,
                         size : libc::size_t,
                         alignment: u8,
		         types: *libc::c_char) -> bool;
    pub fn object_setInstanceVariable(obj : id,
                                      name : *libc::c_char,
                                      value : *libc::c_void);
    pub fn object_getInstanceVariable(obj : id,
                                      name : *libc::c_char,
                                      outValue : **libc::c_void);
    pub fn objc_allocateClassPair(superclass : Class,
                                  name : *libc::c_char,
                                  extraBytes : libc::size_t) -> Class;
    pub fn objc_getClass(name : *libc::c_char) -> id;
    pub fn objc_msgSend(theReceiver : id, theSelector : SEL) -> id;
    pub fn objc_registerClassPair(cls : Class);
    pub fn sel_registerName(name : *libc::c_char) -> SEL;
}

#[cfg(test)]
mod test {
    use std::{io, libc};
    use super::*;

    #[test]
    #[fixed_stack_segment]
    pub fn test_nsapp() {
        let klass = do "NSApplication".to_c_str().with_ref |s| {
            unsafe {
                objc_getClass(s)
            }
        };

        let sel = do "sharedApplication".to_c_str().with_ref |s| {
            unsafe {
                sel_registerName(s)
            }
        };

        unsafe {
            let nsapp = objc_msgSend(klass, sel);
            io::println(format!("nsapp: {:d}", (nsapp as int)));
        }
    }

    #[test]
    #[fixed_stack_segment]
    pub fn test_custom_obj() {
        extern fn MyObject_doSomething(this : id, _sel : SEL) -> id {
            io::println("doSomething");
            return this;
        }

        let NSObject = do "NSObject".to_c_str().with_ref |s| {
            unsafe {
                objc_getClass(s)
            }
        };
        let MyObject = do "MyObject".to_c_str().with_ref |s| {
            unsafe {
                objc_allocateClassPair(NSObject, s, 0 as libc::size_t)
            }
        };
        let doSomething = do "doSomething".to_c_str().with_ref |s| {
            unsafe {
                sel_registerName(s)
            }
        };
        let _ = do "@@:".to_c_str().with_ref |types| {
            unsafe {
                class_addMethod(MyObject,
                                doSomething,
                                MyObject_doSomething,
                                types)
            }
        };

        unsafe {
            objc_registerClassPair(MyObject);
        }

        let alloc = do "alloc".to_c_str().with_ref |s| {
            unsafe { sel_registerName(s) }
        };
        let init = do "init".to_c_str().with_ref |s| {
            unsafe { sel_registerName(s) }
        };

        unsafe {
            let mut obj = objc_msgSend(MyObject, alloc);
            obj = objc_msgSend(obj, init);
            objc_msgSend(obj, doSomething);
        }
    }
}

/// Invokes the given selector, which must have the signature:
///
///     double f();
#[fixed_stack_segment]
pub fn msg_send_double(theReceiver: id, theSelector: SEL) -> f64 {
    unsafe {
        invoke_msg_double(theReceiver, theSelector)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     id f();
#[fixed_stack_segment]
pub fn msg_send_id(theReceiver: id, theSelector: SEL) -> id {
    unsafe {
        invoke_msg_id(theReceiver, theSelector)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     id f(NSRect a);
#[fixed_stack_segment]
pub fn msg_send_id_NSRect(theReceiver: id, theSelector: SEL, a: NSRect) -> id {
    unsafe {
        invoke_msg_id_NSRect(theReceiver, theSelector, &a)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     id f(id a, id b, id c, id e, id f);
#[fixed_stack_segment]
pub fn msg_send_id_id_id_id_id_id(theReceiver: id,
                                  theSelector: SEL,
                                  a: id,
                                  b: id,
                                  c: id,
                                  d: id,
                                  e: id)
                                  -> id {
    unsafe {
        invoke_msg_id_id_id_id_id_id(theReceiver, theSelector, a, b, c, d, e)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     long f();
#[fixed_stack_segment]
pub fn msg_send_long(theReceiver: id, theSelector: SEL) -> c_long {
    unsafe {
        invoke_msg_long(theReceiver, theSelector)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     void f();
#[fixed_stack_segment]
pub fn msg_send_void(theReceiver: id, theSelector: SEL) {
    unsafe {
        invoke_msg_void(theReceiver, theSelector)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     void f(BOOL a);
#[fixed_stack_segment]
pub fn msg_send_void_bool(theReceiver: id, theSelector: SEL, a: bool) {
    unsafe {
        invoke_msg_void_bool(theReceiver, theSelector, a)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     void f(id a);
#[fixed_stack_segment]
pub fn msg_send_void_id(theReceiver: id, theSelector: SEL, a: id) {
    unsafe {
        invoke_msg_void_id(theReceiver, theSelector, a)
    }
}

#[link_args = "-L. -lmsgsend"]
#[nolink]
extern {
    fn invoke_msg_double(theReceiver: id, theSelector: SEL) -> f64;
    fn invoke_msg_id(theReceiver: id, theSelector: SEL) -> id;
    fn invoke_msg_id_id_id_id_id_id(theReceiver: id,
                                    theSelector: SEL,
                                    a: id,
                                    b: id,
                                    c: id,
                                    d: id,
                                    e: id)
                                    -> id;
    fn invoke_msg_id_NSRect(theReceiver: id, theSelector: SEL, a: &NSRect) -> id;
    fn invoke_msg_long(theReceiver: id, theSelector: SEL) -> c_long;
    fn invoke_msg_void(theReceiver: id, theSelector: SEL);
    fn invoke_msg_void_bool(theReceiver: id, theSelector: SEL, a: bool);
    fn invoke_msg_void_id(theReceiver: id, theSelector: SEL, a: id);
}

<commit_msg>Remove use of std::io.<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use appkit::NSRect;

use std::libc;
use std::libc::c_long;

pub type id = libc::intptr_t;
pub type Class = libc::intptr_t;
pub type IMP = extern "C" fn(id, SEL) -> id;
pub type SEL = libc::intptr_t;
pub type Ivar = libc::intptr_t;

pub static NIL : id = 0 as id;

extern {
    pub fn class_addMethod(cls: Class, name: SEL, imp: IMP, types: *libc::c_char) -> bool;
    pub fn class_addIvar(cls : Class,
                         name : *libc::c_char,
                         size : libc::size_t,
                         alignment: u8,
		         types: *libc::c_char) -> bool;
    pub fn object_setInstanceVariable(obj : id,
                                      name : *libc::c_char,
                                      value : *libc::c_void);
    pub fn object_getInstanceVariable(obj : id,
                                      name : *libc::c_char,
                                      outValue : **libc::c_void);
    pub fn objc_allocateClassPair(superclass : Class,
                                  name : *libc::c_char,
                                  extraBytes : libc::size_t) -> Class;
    pub fn objc_getClass(name : *libc::c_char) -> id;
    pub fn objc_msgSend(theReceiver : id, theSelector : SEL) -> id;
    pub fn objc_registerClassPair(cls : Class);
    pub fn sel_registerName(name : *libc::c_char) -> SEL;
}

#[cfg(test)]
mod test {
    use std::libc;
    use super::*;

    #[test]
    #[fixed_stack_segment]
    pub fn test_nsapp() {
        let klass = do "NSApplication".to_c_str().with_ref |s| {
            unsafe {
                objc_getClass(s)
            }
        };

        let sel = do "sharedApplication".to_c_str().with_ref |s| {
            unsafe {
                sel_registerName(s)
            }
        };

        unsafe {
            let nsapp = objc_msgSend(klass, sel);
            println!("nsapp: {:d}", (nsapp as int));
        }
    }

    #[test]
    #[fixed_stack_segment]
    pub fn test_custom_obj() {
        extern fn MyObject_doSomething(this : id, _sel : SEL) -> id {
            println!("doSomething");
            return this;
        }

        let NSObject = do "NSObject".to_c_str().with_ref |s| {
            unsafe {
                objc_getClass(s)
            }
        };
        let MyObject = do "MyObject".to_c_str().with_ref |s| {
            unsafe {
                objc_allocateClassPair(NSObject, s, 0 as libc::size_t)
            }
        };
        let doSomething = do "doSomething".to_c_str().with_ref |s| {
            unsafe {
                sel_registerName(s)
            }
        };
        let _ = do "@@:".to_c_str().with_ref |types| {
            unsafe {
                class_addMethod(MyObject,
                                doSomething,
                                MyObject_doSomething,
                                types)
            }
        };

        unsafe {
            objc_registerClassPair(MyObject);
        }

        let alloc = do "alloc".to_c_str().with_ref |s| {
            unsafe { sel_registerName(s) }
        };
        let init = do "init".to_c_str().with_ref |s| {
            unsafe { sel_registerName(s) }
        };

        unsafe {
            let mut obj = objc_msgSend(MyObject, alloc);
            obj = objc_msgSend(obj, init);
            objc_msgSend(obj, doSomething);
        }
    }
}

/// Invokes the given selector, which must have the signature:
///
///     double f();
#[fixed_stack_segment]
pub fn msg_send_double(theReceiver: id, theSelector: SEL) -> f64 {
    unsafe {
        invoke_msg_double(theReceiver, theSelector)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     id f();
#[fixed_stack_segment]
pub fn msg_send_id(theReceiver: id, theSelector: SEL) -> id {
    unsafe {
        invoke_msg_id(theReceiver, theSelector)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     id f(NSRect a);
#[fixed_stack_segment]
pub fn msg_send_id_NSRect(theReceiver: id, theSelector: SEL, a: NSRect) -> id {
    unsafe {
        invoke_msg_id_NSRect(theReceiver, theSelector, &a)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     id f(id a, id b, id c, id e, id f);
#[fixed_stack_segment]
pub fn msg_send_id_id_id_id_id_id(theReceiver: id,
                                  theSelector: SEL,
                                  a: id,
                                  b: id,
                                  c: id,
                                  d: id,
                                  e: id)
                                  -> id {
    unsafe {
        invoke_msg_id_id_id_id_id_id(theReceiver, theSelector, a, b, c, d, e)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     long f();
#[fixed_stack_segment]
pub fn msg_send_long(theReceiver: id, theSelector: SEL) -> c_long {
    unsafe {
        invoke_msg_long(theReceiver, theSelector)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     void f();
#[fixed_stack_segment]
pub fn msg_send_void(theReceiver: id, theSelector: SEL) {
    unsafe {
        invoke_msg_void(theReceiver, theSelector)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     void f(BOOL a);
#[fixed_stack_segment]
pub fn msg_send_void_bool(theReceiver: id, theSelector: SEL, a: bool) {
    unsafe {
        invoke_msg_void_bool(theReceiver, theSelector, a)
    }
}

/// Invokes the given selector, which must have the signature:
///
///     void f(id a);
#[fixed_stack_segment]
pub fn msg_send_void_id(theReceiver: id, theSelector: SEL, a: id) {
    unsafe {
        invoke_msg_void_id(theReceiver, theSelector, a)
    }
}

#[link_args = "-L. -lmsgsend"]
#[nolink]
extern {
    fn invoke_msg_double(theReceiver: id, theSelector: SEL) -> f64;
    fn invoke_msg_id(theReceiver: id, theSelector: SEL) -> id;
    fn invoke_msg_id_id_id_id_id_id(theReceiver: id,
                                    theSelector: SEL,
                                    a: id,
                                    b: id,
                                    c: id,
                                    d: id,
                                    e: id)
                                    -> id;
    fn invoke_msg_id_NSRect(theReceiver: id, theSelector: SEL, a: &NSRect) -> id;
    fn invoke_msg_long(theReceiver: id, theSelector: SEL) -> c_long;
    fn invoke_msg_void(theReceiver: id, theSelector: SEL);
    fn invoke_msg_void_bool(theReceiver: id, theSelector: SEL, a: bool);
    fn invoke_msg_void_id(theReceiver: id, theSelector: SEL, a: id);
}

<|endoftext|>


<commit_before>extern mod std;

use std::run;
use std::str;
use std::option::*;
use std::trie::*;
use std::libc::{execvp, perror};
use std::c_str::*;
use std::vec;
use std::ptr;

fn detached_session_number(line: &str) -> Option<uint> {
    if line.ends_with("(attached)") {
        None
    } else {
        line.split_iter(':').next().and_then(|s| from_str(s))
    }
}

fn detached_sessions(output: ~str) -> TrieSet {
    output.line_iter().filter_map(|line| {
            detached_session_number(line)
    }).collect()
}

#[fixed_stack_segment]
fn exec_program(program: &str, args: &[~str]) {
    do program.with_c_str() |c_program| {
        // I don't much care about the ownership of the strings here
        // at this point, so let's just fail if execvp isn't working.
        unsafe {
            let mut c_args = args.map(|arg| { arg.to_c_str().unwrap() });
            c_args.push(ptr::null());
            execvp(c_program, vec::raw::to_ptr(c_args));
            perror("Running tmux failed:".to_c_str().unwrap());
        }
        fail!(fmt!("Couldn't exec %s", program));
    }
}

fn main() {
    let proc = run::process_output("tmux", &[~"list-sessions"]);
    if proc.status != 0 {
        fail!(fmt!("Tmux exited with an error status: %d", proc.status));
    }
    let output = str::from_utf8(proc.output);
    let sessions = detached_sessions(output);
    match sessions.iter().next() {
        Some(n) => {
            let session = n.to_str();
            exec_program("tmux", &[~"tmux", ~"attach-session", ~"-t", session]);
        }
        _ => { exec_program("tmux", &[~"tmux"]); }
    }
}

#[test]
fn test_session_is_attached() {
    assert!(session_is_attached("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)"));
    assert!(!session_is_attached("20: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]"));
}

#[test]
fn test_session_number_with_numbers(){
    match(detached_session_number("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]")) {
        Some(11) => (),
        Some(n) => fail!(fmt!("Should have returned 11, got %u!", n)),
        None => fail!("Should have returned something, got nothing"),
    }
}

#[test]
fn test_session_number_with_strings(){
    match(detached_session_number("oink: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]")) {
        Some(n) => fail!(fmt!("Should have returned None, got %u!", n)),
        None => ()
    }
}

#[test]
fn test_session_number_with_attached_session(){
    match(detached_session_number("1: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)")) {
        Some(n) => fail!(fmt!("Should have returned None, got %u!", n)),
        None => ()
    }
}

#[test]
fn test_detached_sessions() {
    let set = detached_sessions(~"3: foo (attached)\n2: bar\n15: oink\n4: baz (attached)\nfoo: baz");
    // attached sessions:
    assert!(!set.contains(&3));
    assert!(!set.contains(&4));

    // detached sessions should be present:
    assert!(set.contains(&15));
    assert!(set.contains(&2));

    // missing session:
    assert!(!set.contains(&1));
}
<commit_msg>Get rid of now-outdated session_is_attached test<commit_after>extern mod std;

use std::run;
use std::str;
use std::option::*;
use std::trie::*;
use std::libc::{execvp, perror};
use std::c_str::*;
use std::vec;
use std::ptr;

fn detached_session_number(line: &str) -> Option<uint> {
    if line.ends_with("(attached)") {
        None
    } else {
        line.split_iter(':').next().and_then(|s| from_str(s))
    }
}

fn detached_sessions(output: ~str) -> TrieSet {
    output.line_iter().filter_map(|line| {
            detached_session_number(line)
    }).collect()
}

#[fixed_stack_segment]
fn exec_program(program: &str, args: &[~str]) {
    do program.with_c_str() |c_program| {
        // I don't much care about the ownership of the strings here
        // at this point, so let's just fail if execvp isn't working.
        unsafe {
            let mut c_args = args.map(|arg| { arg.to_c_str().unwrap() });
            c_args.push(ptr::null());
            execvp(c_program, vec::raw::to_ptr(c_args));
            perror("Running tmux failed:".to_c_str().unwrap());
        }
        fail!(fmt!("Couldn't exec %s", program));
    }
}

fn main() {
    let proc = run::process_output("tmux", &[~"list-sessions"]);
    if proc.status != 0 {
        fail!(fmt!("Tmux exited with an error status: %d", proc.status));
    }
    let output = str::from_utf8(proc.output);
    let sessions = detached_sessions(output);
    match sessions.iter().next() {
        Some(n) => {
            let session = n.to_str();
            exec_program("tmux", &[~"tmux", ~"attach-session", ~"-t", session]);
        }
        _ => { exec_program("tmux", &[~"tmux"]); }
    }
}

#[test]
fn test_session_number_with_numbers(){
    match(detached_session_number("11: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]")) {
        Some(11) => (),
        Some(n) => fail!(fmt!("Should have returned 11, got %u!", n)),
        None => fail!("Should have returned something, got nothing"),
    }
}

#[test]
fn test_session_number_with_strings(){
    match(detached_session_number("oink: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65]")) {
        Some(n) => fail!(fmt!("Should have returned None, got %u!", n)),
        None => ()
    }
}

#[test]
fn test_session_number_with_attached_session(){
    match(detached_session_number("1: 1 windows (created Sat Sep 14 17:11:29 2013) [130x65] (attached)")) {
        Some(n) => fail!(fmt!("Should have returned None, got %u!", n)),
        None => ()
    }
}

#[test]
fn test_detached_sessions() {
    let set = detached_sessions(~"3: foo (attached)\n2: bar\n15: oink\n4: baz (attached)\nfoo: baz");
    // attached sessions:
    assert!(!set.contains(&3));
    assert!(!set.contains(&4));

    // detached sessions should be present:
    assert!(set.contains(&15));
    assert!(set.contains(&2));

    // missing session:
    assert!(!set.contains(&1));
}
<|endoftext|>


<commit_before>extern crate websocket;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::async::Server;

use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};
use futures_cpupool::CpuPool;

use std::sync::{RwLock, Arc};
use std::thread;
use std::rc::Rc;
use std::fmt::Debug;
use std::time::Duration;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let remote = core.remote();
    let server = Server::bind("localhost:8081", &handle).unwrap();
    let pool = Rc::new(CpuPool::new_num_cpus());
    let state = Arc::new(RwLock::new(State::new()));
    let (read_channel_out, read_channel_in) = futures::sync::mpsc::unbounded();
    let (write_channel_out, write_channel_in) = futures::sync::mpsc::unbounded();
    let handle_inner = handle.clone();
    let connection_handler = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(move |(upgrade, addr)| {
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle_inner);
                return Ok(());
            }
            let read_channel_out = read_channel_out.clone();
            let write_channel_out = write_channel_out.clone();
            upgrade
                .use_protocol("rust-websocket")
                .accept()
                .and_then(move |(framed, _)| {
                    let (sink, stream) = framed.split();
                    read_channel_out.send(stream).wait().unwrap();
                    write_channel_out.send(sink).wait().unwrap();
                    Ok(())
                })
                .wait()
                .unwrap();
            Ok(())
        })
        .map_err(|_| ());

    let state_read = state.clone();
    let remote_write = remote.clone();
    let read_handler = pool.spawn_fn( || {
        read_channel_in.for_each(move |stream| {
            let state_read = state_read.clone();
            remote_write.spawn(|_| {
                stream
                    .for_each(move |msg|{
                        handle_incoming(&mut state_read.write().unwrap(), &msg);
                        Ok(())
                    })
                    .map_err(|_| ())
            });
            Ok(())
        })
    });

    let write_handler = pool.spawn_fn(move || {
        write_channel_in.for_each(move |sink| {
            let state_write = state.clone();
            future::loop_fn(sink, move |sink| {
                thread::sleep(Duration::from_millis(100));
                send(&state_write.read().unwrap(), sink)
                    .map(|sink| Loop::Continue(sink))
                    .map_err(|_| Loop::Break::<(), SplitSink>(()))
            }).map_err(|_| ())
        })
    });

    let handlers = connection_handler.select2(read_handler.select(write_handler));
    core.run(handlers).map_err(|_| println!("err")).unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("Error in {}: '{:?}'", desc, e))
                     .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(state: &mut State, msg: &OwnedMessage) {
    match msg {
        &OwnedMessage::Text(ref txt) => {
            println!("Received message: {}", txt);
            state.msg = txt.clone();
        }
        _ => {}
    }
}

type SplitSink = futures::stream::SplitSink<
                    websocket::client::async::Framed<tokio_core::net::TcpStream,
                    websocket::async::MessageCodec<websocket::OwnedMessage>>
                >;

fn send(state: &State, sink: SplitSink) -> futures::sink::Send<SplitSink> {
    let msg = serde_json::to_string(&state).unwrap();
    println!("Sending message: {}", msg);
    sink.send(OwnedMessage::Text(msg))
}

#[derive(Serialize)]
struct State {
    msg: String,
}

impl State {
    fn new() -> State {
        State { msg: "git gud".to_string() }
    }
}
<commit_msg>Fix game loop<commit_after>extern crate websocket;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::async::Server;

use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};
use futures_cpupool::CpuPool;

use std::sync::{RwLock, Arc};
use std::thread;
use std::rc::Rc;
use std::fmt::Debug;
use std::time::Duration;
use std::ops::Deref;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let remote = core.remote();
    let server = Server::bind("localhost:8081", &handle).unwrap();
    let pool = Rc::new(CpuPool::new_num_cpus());
    let connections = Arc::new(RwLock::new(Vec::new()));
    let state = Arc::new(RwLock::new(State::new()));
    let (read_channel_out, read_channel_in) = futures::sync::mpsc::unbounded();
    let (write_channel_out, write_channel_in) = futures::sync::mpsc::unbounded();
    let handle_inner = handle.clone();
    let connection_handler = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(move |(upgrade, addr)| {
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle_inner);
                return Ok(());
            }
            let read_channel_out = read_channel_out.clone();
            let write_channel_out = write_channel_out.clone();
            upgrade
                .use_protocol("rust-websocket")
                .accept()
                .and_then(move |(framed, _)| {
                    let (sink, stream) = framed.split();
                    read_channel_out.send(stream).wait().unwrap();
                    write_channel_out.send(sink).wait().unwrap();
                    Ok(())
                })
                .wait()
                .unwrap();
            Ok(())
        })
        .map_err(|_| ());

    let state_read = state.clone();
    let remote_write = remote.clone();
    let read_handler = pool.spawn_fn( || {
        read_channel_in.for_each(move |stream| {
            let state_read = state_read.clone();
            remote_write.spawn(|_| {
                stream
                    .for_each(move |msg|{
                        handle_incoming(&mut state_read.write().unwrap(), &msg);
                        Ok(())
                    })
                    .map_err(|_| ())
            });
            Ok(())
        })
    });

    let connections_inner = connections.clone();
    let write_handler = pool.spawn_fn(move || {
        write_channel_in.for_each(move |sink| {
            let (write_out, write_in) = futures::sync::mpsc::unbounded();
            connections_inner.write().unwrap().push(write_out);
            remote.spawn(move |_| {
                write_in.fold(sink, |mut sink, state:Arc<RwLock<State>>|{
                    let msg = serde_json::to_string(&state.read().unwrap().deref()).unwrap();
                    println!("Sending message: {}", msg);
                    sink.start_send(OwnedMessage::Text(msg)).unwrap();
                    Ok((sink))
                }).map(|_| ())
            });
            Ok(())
        })
    });

    let game_loop = pool.spawn_fn(move || {
         future::loop_fn(connections, move |connections| {
                thread::sleep(Duration::from_millis(100));
                for conn in connections.write().unwrap().iter() {
                    let state = state.clone();
                    conn.send(state).unwrap();
                }
                match 1 {
                    1=>Ok(Loop::Continue(connections)),
                    2=>Ok(Loop::Break(())),
                    _=>Err(())
                }
        })
    });

    let handlers = game_loop.select2(connection_handler.select2(read_handler.select(write_handler)));
    core.run(handlers).map_err(|_| println!("err")).unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("Error in {}: '{:?}'", desc, e))
                     .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(state: &mut State, msg: &OwnedMessage) {
    match msg {
        &OwnedMessage::Text(ref txt) => {
            println!("Received message: {}", txt);
            state.msg = txt.clone();
        }
        _ => {}
    }
}

#[derive(Serialize)]
struct State {
    msg: String,
}

impl State {
    fn new() -> State {
        State { msg: "git gud".to_string() }
    }
}
<|endoftext|>


<commit_before>///  Specifies the type of antialiasing to do when rendering text or shapes.
///
/// As it is not necessarily clear from the above what advantages a particular antialias method provides, since 1.12, there is also a set of hints: CAIRO_ANTIALIAS_FAST: Allow the backend to degrade raster quality for speed CAIRO_ANTIALIAS_GOOD: A balance between speed and quality CAIRO_ANTIALIAS_BEST: A high-fidelity, but potentially slow, raster mode
///
/// These make no guarantee on how the backend will perform its rasterisation (if it even rasterises!), nor that they have any differing effect other than to enable some form of antialiasing. In the case of glyph rendering, CAIRO_ANTIALIAS_FAST and CAIRO_ANTIALIAS_GOOD will be mapped to CAIRO_ANTIALIAS_GRAY, with CAIRO_ANTALIAS_BEST being equivalent to CAIRO_ANTIALIAS_SUBPIXEL.
///
/// The interpretation of CAIRO_ANTIALIAS_DEFAULT is left entirely up to the backend, typically this will be similar to CAIRO_ANTIALIAS_GOOD.
///
/// CAIRO_ANTIALIAS_DEFAULT
///	Use the default antialiasing for the subsystem and target device, since 1.0
///
/// CAIRO_ANTIALIAS_NONE
///	Use a bilevel alpha mask, since 1.0
///
/// CAIRO_ANTIALIAS_GRAY
///	Perform single-color antialiasing (using shades of gray for black text on a white background, for example), since 1.0
///
/// CAIRO_ANTIALIAS_SUBPIXEL
///	Perform antialiasing by taking advantage of the order of subpixel elements on devices such as LCD panels, since 1.0
///
/// CAIRO_ANTIALIAS_FAST
///	Hint that the backend should perform some antialiasing but prefer speed over quality, since 1.12
///
/// CAIRO_ANTIALIAS_GOOD
///	The backend should balance quality against performance, since 1.12
///
/// CAIRO_ANTIALIAS_BEST
///	Hint that the backend should render at the highest quality, sacrificing speed if necessary, since 1.12
///
/// Since 1.0
#[repr(i32)]
pub enum Antialias {
  Default = 0,
  None = 1,
  Gray = 2,
  Subpixel = 3,
  Fast = 4,
  Good = 5,
  Best = 6
}

<commit_msg>Copied Cairo documentation for antialias<commit_after>//! Describe type of antialiasing when rendering text or shapes

///  Specifies the type of antialiasing to do when rendering text or shapes.
///
/// As it is not necessarily clear from the above what advantages a particular antialias method provides, since 1.12, there is also a set of hints: CAIRO_ANTIALIAS_FAST: Allow the backend to degrade raster quality for speed CAIRO_ANTIALIAS_GOOD: A balance between speed and quality CAIRO_ANTIALIAS_BEST: A high-fidelity, but potentially slow, raster mode
///
/// These make no guarantee on how the backend will perform its rasterisation (if it even rasterises!), nor that they have any differing effect other than to enable some form of antialiasing. In the case of glyph rendering, CAIRO_ANTIALIAS_FAST and CAIRO_ANTIALIAS_GOOD will be mapped to CAIRO_ANTIALIAS_GRAY, with CAIRO_ANTALIAS_BEST being equivalent to CAIRO_ANTIALIAS_SUBPIXEL.
///
/// The interpretation of CAIRO_ANTIALIAS_DEFAULT is left entirely up to the backend, typically this will be similar to CAIRO_ANTIALIAS_GOOD.
///
/// Since 1.0
#[repr(i32)]
pub enum Antialias {
  /// Use the default antialiasing for the subsystem and target device, since 1.0
  Default = 0,
  /// Use a bilevel alpha mask, since 1.0
  None = 1,
  /// Perform single-color antialiasing (using shades of gray for black text on a white background, for example), since 1.0
  Gray = 2,
  /// Perform antialiasing by taking advantage of the order of subpixel elements on devices such as LCD panels, since 1.0
  Subpixel = 3,
  /// Hint that the backend should perform some antialiasing but prefer speed over quality, since 1.12
  Fast = 4,
  /// The backend should balance quality against performance, since 1.12
  Good = 5,
  ///Hint that the backend should render at the highest quality, sacrificing speed if necessary, since 1.12
  Best = 6
}

<|endoftext|>


<commit_before>///
/// Describes the possible behaviors of the `Tree::remove_node` method.
///
pub enum RemoveBehavior {
    ///
    /// All children will be dropped recursively.  In other words, the entire sub-tree of the `Node`
    /// being removed will be dropped from the tree.  Those `Node`s will no longer exist and
    /// cannot be accessed even if you have the `NodeId` the previously pointed to them.
    ///
    /// This means even without using `Clone` you might end up with copies of invalid `NodeId`s.
    /// Use this behavior with caution.
    ///
    /// ```
    /// use id_tree::Tree;
    /// use id_tree::Node;
    /// use id_tree::RemoveBehavior;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    /// let root_id = tree.set_root(Node::new(0));
    ///
    /// let child_id = tree.insert_with_parent(Node::new(1), &root_id).ok().unwrap();
    /// let grandchild_id = tree.insert_with_parent(Node::new(2), &child_id).ok().unwrap();
    ///
    /// let child = tree.remove_node(child_id, RemoveBehavior::DropChildren).ok().unwrap();
    ///
    /// assert!(tree.get(&grandchild_id).is_err());
    /// assert_eq!(tree.get(&root_id).unwrap().children().len(), 0);
    /// ```
    ///
    DropChildren,

    ///
    /// If the removed `Node` (let's call it `A`) has a parent, `A`'s parent will become the
    /// parent of `A`'s children.  This effectively just shifts them up one level in the `Tree`.
    ///
    /// If `A` doesn't have a parent, then this behaves exactly like
    /// `RemoveBehavior::OrphanChildren`.
    ///
    /// ```
    /// use id_tree::Tree;
    /// use id_tree::Node;
    /// use id_tree::RemoveBehavior;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    /// let root_id = tree.set_root(Node::new(0));
    ///
    /// let child_id = tree.insert_with_parent(Node::new(1), &root_id).ok().unwrap();
    /// let grandchild_id = tree.insert_with_parent(Node::new(2), &child_id).ok().unwrap();
    ///
    /// let child = tree.remove_node(child_id, RemoveBehavior::LiftChildren).ok().unwrap();
    ///
    /// assert!(tree.get(&grandchild_id).is_ok());
    /// assert!(tree.get(&root_id).unwrap().children().contains(&grandchild_id));
    /// ```
    ///
    LiftChildren,

    ///
    /// All children will have their parent references cleared.  This means nothing will point to
    /// them, but they will still exist in the tree.  Those `Node`s can still be accessed provided
    /// that you have the `NodeId` that points to them.
    ///
    /// ```
    /// use id_tree::Tree;
    /// use id_tree::Node;
    /// use id_tree::RemoveBehavior;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    /// let root_id = tree.set_root(Node::new(0));
    ///
    /// let child_id = tree.insert_with_parent(Node::new(1), &root_id).ok().unwrap();
    /// let grandchild_id = tree.insert_with_parent(Node::new(2), &child_id).ok().unwrap();
    ///
    /// let child = tree.remove_node(child_id, RemoveBehavior::OrphanChildren).ok().unwrap();
    ///
    /// assert!(tree.get(&grandchild_id).is_ok());
    /// assert_eq!(tree.get(&root_id).unwrap().children().len(), 0);
    /// ```
    ///
    OrphanChildren,
}

<commit_msg>add MoveBehavior<commit_after>use super::NodeId;

///
/// Describes the possible behaviors of the `Tree::remove_node` method.
///
pub enum RemoveBehavior {
    ///
    /// All children will be dropped recursively.  In other words, the entire sub-tree of the `Node`
    /// being removed will be dropped from the tree.  Those `Node`s will no longer exist and
    /// cannot be accessed even if you have the `NodeId` the previously pointed to them.
    ///
    /// This means even without using `Clone` you might end up with copies of invalid `NodeId`s.
    /// Use this behavior with caution.
    ///
    /// ```
    /// use id_tree::Tree;
    /// use id_tree::Node;
    /// use id_tree::RemoveBehavior;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    /// let root_id = tree.set_root(Node::new(0));
    ///
    /// let child_id = tree.insert_with_parent(Node::new(1), &root_id).ok().unwrap();
    /// let grandchild_id = tree.insert_with_parent(Node::new(2), &child_id).ok().unwrap();
    ///
    /// let child = tree.remove_node(child_id, RemoveBehavior::DropChildren).ok().unwrap();
    ///
    /// assert!(tree.get(&grandchild_id).is_err());
    /// assert_eq!(tree.get(&root_id).unwrap().children().len(), 0);
    /// ```
    ///
    DropChildren,

    ///
    /// If the removed `Node` (let's call it `A`) has a parent, `A`'s parent will become the
    /// parent of `A`'s children.  This effectively just shifts them up one level in the `Tree`.
    ///
    /// If `A` doesn't have a parent, then this behaves exactly like
    /// `RemoveBehavior::OrphanChildren`.
    ///
    /// ```
    /// use id_tree::Tree;
    /// use id_tree::Node;
    /// use id_tree::RemoveBehavior;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    /// let root_id = tree.set_root(Node::new(0));
    ///
    /// let child_id = tree.insert_with_parent(Node::new(1), &root_id).ok().unwrap();
    /// let grandchild_id = tree.insert_with_parent(Node::new(2), &child_id).ok().unwrap();
    ///
    /// let child = tree.remove_node(child_id, RemoveBehavior::LiftChildren).ok().unwrap();
    ///
    /// assert!(tree.get(&grandchild_id).is_ok());
    /// assert!(tree.get(&root_id).unwrap().children().contains(&grandchild_id));
    /// ```
    ///
    LiftChildren,

    ///
    /// All children will have their parent references cleared.  This means nothing will point to
    /// them, but they will still exist in the tree.  Those `Node`s can still be accessed provided
    /// that you have the `NodeId` that points to them.
    ///
    /// ```
    /// use id_tree::Tree;
    /// use id_tree::Node;
    /// use id_tree::RemoveBehavior;
    ///
    /// let mut tree: Tree<i32> = Tree::new();
    /// let root_id = tree.set_root(Node::new(0));
    ///
    /// let child_id = tree.insert_with_parent(Node::new(1), &root_id).ok().unwrap();
    /// let grandchild_id = tree.insert_with_parent(Node::new(2), &child_id).ok().unwrap();
    ///
    /// let child = tree.remove_node(child_id, RemoveBehavior::OrphanChildren).ok().unwrap();
    ///
    /// assert!(tree.get(&grandchild_id).is_ok());
    /// assert_eq!(tree.get(&root_id).unwrap().children().len(), 0);
    /// ```
    ///
    OrphanChildren,
}

///
/// Describes the possible behaviors of the `Tree::move_node` method.
///
pub enum MoveBehavior<'a> {
    ///
    /// Sets the `Node` in question as the new root `Node`, leaving all children in their place (in
    /// other words, they will travel with the `Node` being moved).
    ///
    /// If there is already a root `Node` in place, it will be attached as the last child of the new
    /// root.
    ///
    ToRoot,

    ///
    /// Moves a `Node` inside the `Tree` to a new parent leaving all children in their place.
    ///
    /// If the new parent (let's call it `B`) is a descendant of the `Node` being moved (`A`), then
    /// the direct child of `A` on the path from `A` to `B` will be shifted upwards to take the
    /// place of its parent (`A`).  All other children of `A` will be left alone, meaning they will
    /// travel with it down the `Tree`.
    ///
    /// Please note that during the "shift-up" part of the above scenario, the `Node` being shifted
    /// up will always be added as the last child of its new parent.
    ///
    ToParent(&'a NodeId),
}

<|endoftext|>


<commit_before>use bytes::Bytes;
use futures::{Poll, Stream};
use futures::sync::mpsc;
use tokio_proto;

use http::Chunk;

pub type TokioBody = tokio_proto::streaming::Body<Chunk, ::Error>;

/// A `Stream` for `Chunk`s used in requests and responses.
#[derive(Debug)]
pub struct Body(TokioBody);

impl Body {
    /// Return an empty body stream
    #[inline]
    pub fn empty() -> Body {
        Body(TokioBody::empty())
    }

    /// Return a body stream with an associated sender half
    #[inline]
    pub fn pair() -> (mpsc::Sender<Result<Chunk, ::Error>>, Body) {
        let (tx, rx) = TokioBody::pair();
        let rx = Body(rx);
        (tx, rx)
    }
}

impl Default for Body {
    #[inline]
    fn default() -> Body {
        Body::empty()
    }
}

impl Stream for Body {
    type Item = Chunk;
    type Error = ::Error;

    #[inline]
    fn poll(&mut self) -> Poll<Option<Chunk>, ::Error> {
        self.0.poll()
    }
}

impl From<Body> for tokio_proto::streaming::Body<Chunk, ::Error> {
    #[inline]
    fn from(b: Body) -> tokio_proto::streaming::Body<Chunk, ::Error> {
        b.0
    }
}

impl From<tokio_proto::streaming::Body<Chunk, ::Error>> for Body {
    #[inline]
    fn from(tokio_body: tokio_proto::streaming::Body<Chunk, ::Error>) -> Body {
        Body(tokio_body)
    }
}

impl From<mpsc::Receiver<Result<Chunk, ::Error>>> for Body {
    #[inline]
    fn from(src: mpsc::Receiver<Result<Chunk, ::Error>>) -> Body {
        Body(src.into())
    }
}

impl From<Chunk> for Body {
    #[inline]
    fn from (chunk: Chunk) -> Body {
        Body(TokioBody::from(chunk))
    }
}

impl From<Bytes> for Body {
    #[inline]
    fn from (bytes: Bytes) -> Body {
        Body(TokioBody::from(Chunk::from(bytes)))
    }
}

impl From<Vec<u8>> for Body {
    #[inline]
    fn from (vec: Vec<u8>) -> Body {
        Body(TokioBody::from(Chunk::from(vec)))
    }
}

impl From<&'static [u8]> for Body {
    #[inline]
    fn from (slice: &'static [u8]) -> Body {
        Body(TokioBody::from(Chunk::from(slice)))
    }
}

impl From<String> for Body {
    #[inline]
    fn from (s: String) -> Body {
        Body(TokioBody::from(Chunk::from(s.into_bytes())))
    }
}

impl From<&'static str> for Body {
    #[inline]
    fn from (slice: &'static str) -> Body {
        Body(TokioBody::from(Chunk::from(slice.as_bytes())))
    }
}

fn _assert_send_sync() {
    fn _assert_send<T: Send>() {}
    fn _assert_sync<T: Sync>() {}

    _assert_send::<Body>();
    _assert_send::<Chunk>();
    _assert_sync::<Chunk>();
}

#[test]
fn test_body_stream_concat() {
    use futures::{Sink, Stream, Future};
    let (tx, body) = Body::pair();

    ::std::thread::spawn(move || {
        let tx = tx.send(Ok("hello ".into())).wait().unwrap();
        tx.send(Ok("world".into())).wait().unwrap();
    });

    let total = body.concat2().wait().unwrap();
    assert_eq!(total.as_ref(), b"hello world");

}
<commit_msg>test(http): fix Body.concat test<commit_after>use bytes::Bytes;
use futures::{Poll, Stream};
use futures::sync::mpsc;
use tokio_proto;

use http::Chunk;

pub type TokioBody = tokio_proto::streaming::Body<Chunk, ::Error>;

/// A `Stream` for `Chunk`s used in requests and responses.
#[derive(Debug)]
pub struct Body(TokioBody);

impl Body {
    /// Return an empty body stream
    #[inline]
    pub fn empty() -> Body {
        Body(TokioBody::empty())
    }

    /// Return a body stream with an associated sender half
    #[inline]
    pub fn pair() -> (mpsc::Sender<Result<Chunk, ::Error>>, Body) {
        let (tx, rx) = TokioBody::pair();
        let rx = Body(rx);
        (tx, rx)
    }
}

impl Default for Body {
    #[inline]
    fn default() -> Body {
        Body::empty()
    }
}

impl Stream for Body {
    type Item = Chunk;
    type Error = ::Error;

    #[inline]
    fn poll(&mut self) -> Poll<Option<Chunk>, ::Error> {
        self.0.poll()
    }
}

impl From<Body> for tokio_proto::streaming::Body<Chunk, ::Error> {
    #[inline]
    fn from(b: Body) -> tokio_proto::streaming::Body<Chunk, ::Error> {
        b.0
    }
}

impl From<tokio_proto::streaming::Body<Chunk, ::Error>> for Body {
    #[inline]
    fn from(tokio_body: tokio_proto::streaming::Body<Chunk, ::Error>) -> Body {
        Body(tokio_body)
    }
}

impl From<mpsc::Receiver<Result<Chunk, ::Error>>> for Body {
    #[inline]
    fn from(src: mpsc::Receiver<Result<Chunk, ::Error>>) -> Body {
        Body(src.into())
    }
}

impl From<Chunk> for Body {
    #[inline]
    fn from (chunk: Chunk) -> Body {
        Body(TokioBody::from(chunk))
    }
}

impl From<Bytes> for Body {
    #[inline]
    fn from (bytes: Bytes) -> Body {
        Body(TokioBody::from(Chunk::from(bytes)))
    }
}

impl From<Vec<u8>> for Body {
    #[inline]
    fn from (vec: Vec<u8>) -> Body {
        Body(TokioBody::from(Chunk::from(vec)))
    }
}

impl From<&'static [u8]> for Body {
    #[inline]
    fn from (slice: &'static [u8]) -> Body {
        Body(TokioBody::from(Chunk::from(slice)))
    }
}

impl From<String> for Body {
    #[inline]
    fn from (s: String) -> Body {
        Body(TokioBody::from(Chunk::from(s.into_bytes())))
    }
}

impl From<&'static str> for Body {
    #[inline]
    fn from (slice: &'static str) -> Body {
        Body(TokioBody::from(Chunk::from(slice.as_bytes())))
    }
}

fn _assert_send_sync() {
    fn _assert_send<T: Send>() {}
    fn _assert_sync<T: Sync>() {}

    _assert_send::<Body>();
    _assert_send::<Chunk>();
    _assert_sync::<Chunk>();
}

#[test]
fn test_body_stream_concat() {
    use futures::{Sink, Stream, Future};
    let (tx, body) = Body::pair();

    ::std::thread::spawn(move || {
        let tx = tx.send(Ok("hello ".into())).wait().unwrap();
        tx.send(Ok("world".into())).wait().unwrap();
    });

    let total = body.concat().wait().unwrap();
    assert_eq!(total.as_ref(), b"hello world");

}
<|endoftext|>


<commit_before>use num::Num;
use point::Point2D;
use size::Size2D;
use cmp::Eq;

struct Rect<T:Copy Num> {
    origin: Point2D<T>,
    size: Size2D<T>

}

fn Rect<T:Copy Num>(origin: Point2D<T>, size: Size2D<T>) -> Rect<T> {
    return Rect {
        origin: copy origin,
        size: copy size
    }
}

impl<T: Copy Num Eq> Rect<T>: Eq {
    pure fn eq(&&other: Rect<T>) -> bool {
        self.origin == other.origin && self.size == other.size
    }
    pure fn ne(&&other: Rect<T>) -> bool {
        !self.eq(other)
    }
}<commit_msg>Add intersects, intersection, union to Rect<commit_after>use num::Num;
use point::Point2D;
use size::Size2D;
use cmp::{Eq, Ord};

struct Rect<T:Copy Num> {
    origin: Point2D<T>,
    size: Size2D<T>

}

fn Rect<T:Copy Num>(origin: Point2D<T>, size: Size2D<T>) -> Rect<T> {
    return Rect {
        origin: copy origin,
        size: copy size
    }
}

impl<T: Copy Num Ord> Rect<T> {
    pure fn intersects(&&other: Rect<T>) -> bool {
        self.origin.x < other.origin.x + other.size.width  &&
       other.origin.x <  self.origin.x +  self.size.width  &&
        self.origin.y < other.origin.y + other.size.height &&
       other.origin.y <  self.origin.y +  self.size.height
    }
}

impl<T: Copy Num Ord> Rect<T> {
    fn intersection(&&other: Rect<T>) -> Option<Rect<T>> {
        if !self.intersects(other) { return None }

        Some(Rect(Point2D(max(self.origin.x, other.origin.x),
                            max(self.origin.y, other.origin.y)),
                  Size2D(min(self.origin.x + self.size.width,
                            other.origin.x + other.size.width),
                         min(self.origin.y + self.size.height,
                            other.origin.y + other.size.height))
        ))
    }

    fn union(&&other: Rect<T>) -> Rect<T> {
        Rect {
            origin: Point2D(min(self.origin.x, other.origin.x),
                            min(self.origin.y, other.origin.y)),
            size: Size2D(max(self.origin.x + self.size.width,
                            other.origin.x + other.size.width),
                         max(self.origin.y + self.size.height,
                            other.origin.y + other.size.height))
        }
    }
}

impl<T: Copy Num> Rect<T> {
    fn move_by(&&other: Point2D<T>) -> Rect<T> {
        Rect {
            origin: Point2D(self.origin.x + other.x,
                            self.origin.y + other.y),
            size: copy self.size
        }
    }
}

impl<T: Copy Num Eq> Rect<T>: Eq {
    pure fn eq(&&other: Rect<T>) -> bool {
        self.origin == other.origin && self.size == other.size
    }
    pure fn ne(&&other: Rect<T>) -> bool {
        !self.eq(other)
    }
}

pure fn min<T: Copy Num Ord>(x: T, y: T) -> T {
    if x <= y { x } else { y }
}

pure fn max<T: Copy Num Ord>(x: T, y: T) -> T {
    if x >= y { x } else { y }
}<|endoftext|>


<commit_before>#![crate_name="world"]

extern crate rand;
extern crate rustc_serialize;
extern crate num;
extern crate vec_map;
#[macro_use] extern crate calx_ecs;
extern crate calx;
extern crate content;

pub use flags::{Flags};
pub use location::{Location, Chart, Unchart};
pub use msg::{pop_msg};
pub use world::{World};

macro_rules! msg(
    ($($arg:tt)*) => ( ::msg::push(::Msg::Text(format!($($arg)*))))
);

macro_rules! msgln(
    ($($arg:tt)*) => ({
        ::msg::push(::Msg::Text(format!($($arg)*)));
        ::msg::push(::Msg::Text("\n".to_string()));
    })
);

macro_rules! caption(
    ($($arg:tt)*) => ( ::msg::push(::Msg::Caption(format!($($arg)*))))
);

pub mod action;
pub mod components;
pub mod item;
pub mod query;

mod ability;
mod area;
mod entity;
mod flags;
pub mod location;
mod location_set;
mod msg;
mod spatial;
mod spawn;
mod stats;
mod world;

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum FovStatus {
    Seen,
    Remembered,
}

/// Various one-off signals the game sends to the UI layer.
#[derive(Clone, Debug)]
pub enum Msg {
    /// Regular event message
    Text(String),
    /// Important event message to the center of the screen
    Caption(String),
    // TODO: Type of effect.
    Explosion(Location),
    Damage(calx_ecs::Entity),
    Gib(Location),
    Beam(Location, Location),
    /// Beam hitting a wall.
    Sparks(Location),
}

/// Light level value.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Light {
    lum: f32,
}

impl Light {
    pub fn new(lum: f32) -> Light {
        assert!(lum >= 0.0 && lum <= 2.0);
        Light { lum: lum }
    }

    pub fn apply(&self, color: calx::Rgba) -> calx::Rgba {
        let darkness_color = calx::Rgba::new(0.05, 0.10, 0.25, color.a);
        calx::lerp(color * darkness_color, color, self.lum)
    }
}
<commit_msg>Refactoring, it actually compiles again now<commit_after>#![crate_name="world"]

extern crate rand;
extern crate rustc_serialize;
extern crate num;
extern crate vec_map;
#[macro_use] extern crate calx_ecs;
extern crate calx;
extern crate content;

pub use flags::{Flags};
pub use location::{Location, Chart, Unchart};
pub use msg::{pop_msg};
pub use world::{World};
pub use spatial::{Spatial};

macro_rules! msg(
    ($($arg:tt)*) => ( ::msg::push(::Msg::Text(format!($($arg)*))))
);

macro_rules! msgln(
    ($($arg:tt)*) => ({
        ::msg::push(::Msg::Text(format!($($arg)*)));
        ::msg::push(::Msg::Text("\n".to_string()));
    })
);

macro_rules! caption(
    ($($arg:tt)*) => ( ::msg::push(::Msg::Caption(format!($($arg)*))))
);

pub mod action;
pub mod components;
pub mod item;
pub mod query;

mod ability;
mod area;
mod entity;
mod flags;
pub mod location;
mod location_set;
mod msg;
mod spatial;
mod spawn;
mod stats;
mod world;

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum FovStatus {
    Seen,
    Remembered,
}

/// Various one-off signals the game sends to the UI layer.
#[derive(Clone, Debug)]
pub enum Msg {
    /// Regular event message
    Text(String),
    /// Important event message to the center of the screen
    Caption(String),
    // TODO: Type of effect.
    Explosion(Location),
    Damage(calx_ecs::Entity),
    Gib(Location),
    Beam(Location, Location),
    /// Beam hitting a wall.
    Sparks(Location),
}

/// Light level value.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Light {
    lum: f32,
}

impl Light {
    pub fn new(lum: f32) -> Light {
        assert!(lum >= 0.0 && lum <= 2.0);
        Light { lum: lum }
    }

    pub fn apply(&self, color: calx::Rgba) -> calx::Rgba {
        let darkness_color = calx::Rgba::new(0.05, 0.10, 0.25, color.a);
        calx::lerp(color * darkness_color, color, self.lum)
    }
}
<|endoftext|>


<commit_before>//! Library service providers implementation.

extern crate hyper;

use hyper::client::{Client, Response};

/// Used to specify which provider to use to generate a short URL.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Provider {
    /// https://bn.gy provider
    BnGy,
    /// https://is.gd provider
    IsGd,
    /// http://psbe.co provider
    PsbeCo,
    /// http://readbility.com provider
    Rdd,
    /// http://rlu.ru provider
    /// * Attention! If you send a lot of requests from one IP, it can be
    /// blocked. If you plan to add more then 100 URLs in one hour, please let
    /// the technical support know. Otherwise your IP can be blocked
    /// unexpectedly. Prior added URLs can be deleted.
    Rlu,
    /// https://v.gd provider
    VGd,
}

impl Provider {
    /// Converts the Provider variant into its domain name equivilant
    pub fn to_name(&self) -> &str {
        match *self {
            Provider::BnGy => "bn.gy",
            Provider::IsGd => "is.gd",
            Provider::PsbeCo => "psbe.co",
            Provider::Rdd => "readability.com",
            Provider::Rlu => "rlu.ru",
            Provider::VGd => "v.gd",
        }
    }
}

/// Returns a vector of all `Provider` variants.
///
/// The providers which are discouraged from use due to limitations such as
/// rate limitations are at the end of the resultant vector.
pub fn providers() -> Vec<Provider> {
    vec![
        Provider::BnGy,
        Provider::IsGd,
        Provider::Rdd,
        Provider::VGd,

        // The following list are items that are discouraged from use.
        Provider::PsbeCo,
        Provider::Rlu,
    ]
}

fn bngy_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<ShortenedUrl>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</ShortenedUrl>").next() {
        Some(string.to_owned())
    } else {
        None
    }
}

fn bngy_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("https://bn.gy/API.asmx/CreateUrl?real_url={}", url))
        .send()
        .ok()
}

fn isgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn isgd_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("https://is.gd/create.php?format=simple&url={}", url))
        .send()
        .ok()
}

fn psbeco_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<ShortUrl>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</ShortUrl>").next() {
        Some(string.to_owned())
    } else {
        None
    }
}

fn psbeco_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://psbe.co/API.asmx/CreateUrl?real_url={}", url))
        .send()
        .ok()
}

fn rdd_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let value = string.split("\"rdd_url\"")
                      .nth(1).unwrap_or("")
                      .split(",").next().unwrap_or("")
                      .split("\"").nth(1);
    if let Some(string) = value {
        let mut short_url = string.to_owned();
        let _ = short_url.pop();
        Some(short_url)
    } else {
        None
    }
}

fn rdd_request(url: &str, client: &Client) -> Option<Response> {
    client.post("https://readability.com/api/shortener/v1/urls")
        .body(&format!("url={}", url))
        .send()
        .ok()
}

fn rlu_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn rlu_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://rlu.ru/index.sema?a=api&link={}", url))
        .send()
        .ok()
}

fn vgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn vgd_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://v.gd/create.php?format=simple&url={}", url))
        .send()
        .ok()
}

/// Parses the response from a successful request to a provider into the
/// URL-shortened string.
pub fn parse(res: &str, provider: Provider) -> Option<String> {
    match provider {
        Provider::BnGy => bngy_parse(res),
        Provider::IsGd => isgd_parse(res),
        Provider::PsbeCo => psbeco_parse(res),
        Provider::Rdd => rdd_parse(res),
        Provider::Rlu => rlu_parse(res),
        Provider::VGd => vgd_parse(res),
    }
}

/// Performs a request to the short link provider.
/// Response to be parsed or `None` on a error.
pub fn request(url: &str, client: &Client, provider: Provider) -> Option<Response> {
    match provider {
        Provider::BnGy => bngy_request(url, client),
        Provider::IsGd => isgd_request(url, client),
        Provider::PsbeCo => psbeco_request(url, client),
        Provider::Rdd => rdd_request(url, client),
        Provider::Rlu => rlu_request(url, client),
        Provider::VGd => vgd_request(url, client),
    }
}
<commit_msg>Reorder provider vec in order of quality<commit_after>//! Library service providers implementation.

extern crate hyper;

use hyper::client::{Client, Response};

/// Used to specify which provider to use to generate a short URL.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Provider {
    /// https://bn.gy provider
    BnGy,
    /// https://is.gd provider
    IsGd,
    /// http://psbe.co provider
    PsbeCo,
    /// http://readbility.com provider
    Rdd,
    /// http://rlu.ru provider
    /// * Attention! If you send a lot of requests from one IP, it can be
    /// blocked. If you plan to add more then 100 URLs in one hour, please let
    /// the technical support know. Otherwise your IP can be blocked
    /// unexpectedly. Prior added URLs can be deleted.
    Rlu,
    /// https://v.gd provider
    VGd,
}

impl Provider {
    /// Converts the Provider variant into its domain name equivilant
    pub fn to_name(&self) -> &str {
        match *self {
            Provider::BnGy => "bn.gy",
            Provider::IsGd => "is.gd",
            Provider::PsbeCo => "psbe.co",
            Provider::Rdd => "readability.com",
            Provider::Rlu => "rlu.ru",
            Provider::VGd => "v.gd",
        }
    }
}

/// Returns a vector of all `Provider` variants.
///
/// The providers which are discouraged from use due to limitations such as
/// rate limitations are at the end of the resultant vector.
pub fn providers() -> Vec<Provider> {
    vec![
        Provider::IsGd,
        Provider::BnGy,
        Provider::Vgd,
        Provider::Rdd,

        // The following list are items that are discouraged from use.
        Provider::PsbeCo,
        Provider::Rlu,
    ]
}

fn bngy_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<ShortenedUrl>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</ShortenedUrl>").next() {
        Some(string.to_owned())
    } else {
        None
    }
}

fn bngy_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("https://bn.gy/API.asmx/CreateUrl?real_url={}", url))
        .send()
        .ok()
}

fn isgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn isgd_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("https://is.gd/create.php?format=simple&url={}", url))
        .send()
        .ok()
}

fn psbeco_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<ShortUrl>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</ShortUrl>").next() {
        Some(string.to_owned())
    } else {
        None
    }
}

fn psbeco_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://psbe.co/API.asmx/CreateUrl?real_url={}", url))
        .send()
        .ok()
}

fn rdd_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let value = string.split("\"rdd_url\"")
                      .nth(1).unwrap_or("")
                      .split(",").next().unwrap_or("")
                      .split("\"").nth(1);
    if let Some(string) = value {
        let mut short_url = string.to_owned();
        let _ = short_url.pop();
        Some(short_url)
    } else {
        None
    }
}

fn rdd_request(url: &str, client: &Client) -> Option<Response> {
    client.post("https://readability.com/api/shortener/v1/urls")
        .body(&format!("url={}", url))
        .send()
        .ok()
}

fn rlu_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn rlu_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://rlu.ru/index.sema?a=api&link={}", url))
        .send()
        .ok()
}

fn vgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn vgd_request(url: &str, client: &Client) -> Option<Response> {
    client.get(&format!("http://v.gd/create.php?format=simple&url={}", url))
        .send()
        .ok()
}

/// Parses the response from a successful request to a provider into the
/// URL-shortened string.
pub fn parse(res: &str, provider: Provider) -> Option<String> {
    match provider {
        Provider::BnGy => bngy_parse(res),
        Provider::IsGd => isgd_parse(res),
        Provider::PsbeCo => psbeco_parse(res),
        Provider::Rdd => rdd_parse(res),
        Provider::Rlu => rlu_parse(res),
        Provider::VGd => vgd_parse(res),
    }
}

/// Performs a request to the short link provider.
/// Response to be parsed or `None` on a error.
pub fn request(url: &str, client: &Client, provider: Provider) -> Option<Response> {
    match provider {
        Provider::BnGy => bngy_request(url, client),
        Provider::IsGd => isgd_request(url, client),
        Provider::PsbeCo => psbeco_request(url, client),
        Provider::Rdd => rdd_request(url, client),
        Provider::Rlu => rlu_request(url, client),
        Provider::VGd => vgd_request(url, client),
    }
}
<|endoftext|>


<commit_before>use petgraph::graph::IndexType;
use sdl2;
use sdl2::event::Event;
use sdl2::hint;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::rect::{Point};
use sdl2::render::{Renderer, Texture, TextureQuery};

use sdl;
use squaregrid::{GridDirection, SquareGrid};

const INITIAL_W: u32 = 1920;
const INITIAL_H: u32 = 1080;
const LOGICAL_W: u32 = 1920;
const LOGICAL_H: u32 = 1080;
const BLACK: Color = Color::RGB(0, 0, 0);
const WHITE: Color = Color::RGB(0xff, 0xff, 0xff);
const RED: Color = Color::RGB(0xff, 0, 0);
const GREEN: Color = Color::RGB(0, 0xff, 0);
const BLUE: Color = Color::RGB(0, 0, 0xff);
const YELLOW: Color = Color::RGB(0xff, 0xff, 0);

pub fn render_square_grid<GridIndexType>(grid: &SquareGrid<GridIndexType>)
    where GridIndexType: IndexType
{
    let sdl_setup = sdl::init();

    let mut window_builder = sdl_setup.video_subsystem.window("Mazes", INITIAL_W, INITIAL_H);
    let window = window_builder.position_centered()
                               .resizable()
                               .allow_highdpi()
                               .build()
                               .unwrap();
    let mut renderer = window.renderer()
                             .present_vsync()
                             .accelerated()
                             .target_texture()
                             .build()
                             .unwrap();

    // Sets a device independent resolution for rendering.
    // SDL scales to the actual window size, which may change if we allow resizing and is also
    // unknown if we just drop into fullscreen.
    renderer.set_logical_size(LOGICAL_W, LOGICAL_H).unwrap();

    // 0 or 'nearest' == nearest pixel sampling
    // 1 or 'linear' == linear filtering (supported by OpenGL and Direct3D)
    // 2 or 'best' == anisotropic filtering (supported by Direct3D)
    // The hint strings don't seem to be abstracted in the rust source at the moment but we can see
    // the #defines at e.g. https://github.com/spurious/SDL-mirror/blob/master/include/SDL_hints.h
    hint::set("SDL_RENDER_SCALE_QUALITY", "1");
    let mut screen_texture = renderer.create_texture_target(PixelFormatEnum::RGB888,
                                                            LOGICAL_W,
                                                            LOGICAL_H)
                                     .unwrap();
    screen_texture = draw_maze_to_texture(&mut renderer, screen_texture, &grid);

    let mut events = sdl_setup.sdl_context.event_pump().unwrap();
    'running: loop {
        for event in events.poll_iter() {
            match event {
                Event::Quit{..} => break 'running,
                Event::KeyDown{keycode: Some(sdl2::keyboard::Keycode::Q), ..} => break 'running,
                _ => continue,

                // handle redrawing the texture when the windows gets bigger and can show more?
            }
        }

        renderer.set_draw_color(WHITE);
        renderer.clear();
        renderer.copy(&screen_texture, None, None);
        renderer.present();
    }
}

fn draw_maze_to_texture<GridIndexType>(r: &mut Renderer,
                                       t: Texture,
                                       grid: &SquareGrid<GridIndexType>)
                                       -> Texture
    where GridIndexType: IndexType
{
    let (texture_w, texture_h) = match t.query() {
        TextureQuery { width, height, ..} => (width as usize, height as usize),
    };

    // Setup to draw to the given texture. The texture is moved/owned by the `set` call.
    r.render_target()
     .expect("This platform doesn't support render targets")
     .set(t).unwrap(); // Returns the old render target is returned if the function is successful, which we ignore.

    // clear the texture background to white
    r.set_draw_color(WHITE);
    r.clear();

    // Set the maze wall colour.
    r.set_draw_color(BLUE);

    let cell_size_pixels = 10;
    let img_width = cell_size_pixels * grid.dimension();  // usize usize
    let img_height = cell_size_pixels * grid.dimension();

    let x_centering_offset = if img_width  < texture_w { (texture_w - img_width)/2 } else { 0 };
    let y_centering_offset = if img_height < texture_h { (texture_h - img_height)/2 } else { 0 };

    for cell in grid.iter() {
        let column = cell.x as usize;
        let row = cell.y as usize;

        let x1 = ((column * cell_size_pixels) + x_centering_offset) as i32;
        let y1 = ((row * cell_size_pixels) + y_centering_offset) as i32;
        let x2 = (((column + 1) * cell_size_pixels) + x_centering_offset) as i32;
        let y2 = (((row + 1) * cell_size_pixels) + y_centering_offset) as i32;

        // special cases north and west to handle first row and column.
        if grid.neighbour_at_direction(&cell, GridDirection::North).is_none() {
            r.draw_line(Point::new(x1, y1), Point::new(x2, y1)).unwrap();
        }
        if grid.neighbour_at_direction(&cell, GridDirection::West).is_none() {
            r.draw_line(Point::new(x1, y1), Point::new(x1, y2)).unwrap();
        }

        if !grid.is_neighbour_linked(&cell, GridDirection::East) {
            r.draw_line(Point::new(x2, y1), Point::new(x2, y2)).unwrap();
        }
        if !grid.is_neighbour_linked(&cell, GridDirection::South) {
            r.draw_line(Point::new(x1, y2), Point::new(x2, y2)).unwrap();
        }
    }

    // Reseting gives us back ownership of the updated texture and restores the default render target
    let updated_texture: Option<Texture> = r.render_target().unwrap().reset().unwrap();
    updated_texture.unwrap()
}

// For a non-text based view of a maze we need a GUI window if
// we want to see anything live.
// To just write out an image we only need an sdl surface
// to draw on and write out as a PNG?
// Renderer seems to require a window...though the window
// could be hidden I guess?
// - sdl_context -> video_subsystem -> window_builder
// - window_builder options:
//   - *hidden*, fullscreen, opengl enabled, borderless, resizable
//
// sdl2_image provides:
// trait SaveSurface for Surface (save as PNG only)
// trait LoadSurface for Surface (load any texture)
// trait LoadTexture for Renderer
//
// sdl2 provides a Surface accessor on the Renderer type, which
// may also work even if the Renderer is using a Texture?
// I'm guessing that *all* renderers for a window have a Surface, but
// textures as memory locations on the GPU are optional.
// SDL_Surface is just a collection of pixels while SDL_Texture is an
// efficient, driver-specific representation of pixel data
// SDL_Texture on the other hand, is used in a hardware rendering, textures
// are stored in VRAM and you don't have access to it directly as with SDL_Surface.
// The rendering operations are accelerated by GPU, using, internally, either
// OpenGL or DirectX (available only on Windows) API, which in turn are using
// your video hardware, hence hardware rendering name.
// http://stackoverflow.com/questions/21007329/what-is-a-sdl-renderer/21007477#21007477
//
// Actually the section "If your game just wants to get fully-rendered frames to the screen"
// looks like what we want: https://wiki.libsdl.org/MigrationGuide
//
// should we use rendererbuilder target_texture? "Set the renderer to support rendering to a texture."
// does that mean we can render to a texture then do whatever.... renderer.create_texture_target
// renderer. render_target(&mut self) -> Option<RenderTarget>
// When the render target has been set/created the draw_line/fill_rect etc calls are directed to that
// render target.
//
// # drawing every pixel yourself in software and then doing one big blit (software doom etc.)
// - single sdlTexture to represent the screen
// - texture access streaming (frequent content change of the texture)
// - create surface or [u8] as RGBA buffer block of pixels (can convert if need to from other formats)
// - sdl_updatetexture (texture.update) at the end which uploads the pixels to the gpu.
// - [SDL_RenderSetLogicalSize()] so we get scaling as required.
// - render clear
// - rendercopy sdlTexture (put the texture on the gpu in to the backbuffer/framebuffer memory)
// - render present
// Examples:
// - https://github.com/AngryLawyer/rust-sdl2/blob/master/examples/renderer-texture.rs shows streaming texture
//   but does not draw any lines, just messes with a mutable [u8] buffer.
//
// # blitting multiple "sprites" to the screen (treating surfaces as sprites, not pixel buffers)
//   textures tend to be static once uploaded
// - create texture(s) one per sprite etc. +
// - texture access static
// (or createTextureFromSurface as these two steps)
// (it's annoying that the rust api makes it hard to draw a line to a surface)
//
// # Blit surfaces and modify individual pixels in the framebuffer.
//   Round trips--reading data back from textures--can be painfully expensive; generally you want to be pushing data in one direction always.
//   You are probably best off, in this case, keeping everything in software until the final push to the screen, so we'll combine the two previous techniques.
//  - create 'screen' texture
//  - create screen surface
//  - compose the final framebuffer into the sdl_surface.
//  - update texture from screen surface
//  - render clear && render copy 'screen' texture && render present
// N.B.
// SDL_TEXTUREACCESS_STATIC changes rarely, not lockable
// SDL_TEXTUREACCESS_STREAMING changes frequently, lockable
// SDL_TEXTUREACCESS_TARGET can be used as a render target
// Static textures are designed for sprites and backgrounds and other images that don't change much.
// You update them with pixels using SDL_UpdateTexture() (which is pretty slow compared to streaming).
// ```
// let static_maze_texture = renderer.create_texture_static(PixelFormatEnum::RGB888, LOGICAL_W, LOGICAL_H).unwrap();
// Surface::new(...)
// data = surface.without_lock() -> Option<&[u8]> to get the pixel data
// static_maze_texture.update(..., data)
// ```
// Streaming textures are designed for things that update frequently, every few seconds, or every frame.
// You can also update them with SDL_UpdateTexture(), but for optimal performance you lock them, write the pixels,
// and then unlock them.
// Presumably locking allows you to write to them on the GPU directly as you 'stream' the data into them, whereas
// updateTexture just blats the whole thing.
//
// If the renderer is in fullscreen desktop mode we wouldn't know or care what the size
// is but we could then SDL_RenderSetLogicalSize(sdlRenderer, 640, 480); for example.
// The app works with a given logical size but sdl scales it on the GPU, even handling scaling
// with different aspect ratios and letterboxing the difference.
<commit_msg>Rendering maze to surface and save out before rendering as texture on screen.<commit_after>use std::path::Path;

use petgraph::graph::IndexType;
use sdl2;
use sdl2::event::Event;
use sdl2::hint;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::rect::{Point};
use sdl2::render::{Renderer, Texture};
use sdl2::surface::Surface;
use sdl2_image;

use sdl;
use squaregrid::{GridDirection, SquareGrid};

const INITIAL_W: u32 = 1920;
const INITIAL_H: u32 = 1080;
const LOGICAL_W: u32 = 1920;
const LOGICAL_H: u32 = 1080;
const BLACK: Color = Color::RGB(0, 0, 0);
const WHITE: Color = Color::RGB(0xff, 0xff, 0xff);
const RED: Color = Color::RGB(0xff, 0, 0);
const GREEN: Color = Color::RGB(0, 0xff, 0);
const BLUE: Color = Color::RGB(0, 0, 0xff);
const YELLOW: Color = Color::RGB(0xff, 0xff, 0);

pub fn render_square_grid<GridIndexType>(grid: &SquareGrid<GridIndexType>)
    where GridIndexType: IndexType
{
    let sdl_setup = sdl::init();

    let mut window_builder = sdl_setup.video_subsystem.window("Mazes", INITIAL_W, INITIAL_H);
    let window = window_builder.position_centered()
                               .resizable()
                               .allow_highdpi()
                               .build()
                               .unwrap();
    let mut renderer = window.renderer()
                             .present_vsync()
                             .accelerated()
                             .target_texture()
                             .build()
                             .unwrap();

    // We are limited to one renderer per window it seems, at least with the current rust bindings.
    // We want a hardware accelerated window for displaying a maze that uses a texture for performance,
    // but we want a software surface with the maze drawn to it so that we can use sdl2_image save_surface
    // to write out a png.
    // - Renderer::from_surface looks like what we want
    // - Note renderer.into_surface()/into_window() is not what we want
    //   Only extracts the window/surface that already used by the Renderer, basically dropping the other data
    //   that the renderer uses.
    // After rendering to the surface, we can create texture from surface and use a new 2nd renderer to
    // display to a window
    let software_surface = Surface::new(LOGICAL_W, LOGICAL_H, PixelFormatEnum::RGB888).expect("Surface creation failed.");
    let mut software_renderer = Renderer::from_surface(software_surface).expect("Software renderer creation failed.");

    // Sets a device independent resolution for rendering.
    // SDL scales to the actual window size, which may change if we allow resizing and is also
    // unknown if we just drop into fullscreen.
    software_renderer.set_logical_size(LOGICAL_W, LOGICAL_H).unwrap();
    renderer.set_logical_size(LOGICAL_W, LOGICAL_H).unwrap();

    draw_maze(&mut software_renderer, &grid);

    // 0 or 'nearest' == nearest pixel sampling
    // 1 or 'linear' == linear filtering (supported by OpenGL and Direct3D)
    // 2 or 'best' == anisotropic filtering (supported by Direct3D)
    // The hint strings don't seem to be abstracted in the rust source at the moment but we can see
    // the #defines at e.g. https://github.com/spurious/SDL-mirror/blob/master/include/SDL_hints.h
    hint::set("SDL_RENDER_SCALE_QUALITY", "1");

    // Getting the surface from the renderer drops the renderer.
    let maze_surface: Surface = software_renderer.into_surface().expect("Failed to get surface from software renderer");

    // WTF: the trait `sdl2_image::SaveSurface` is not implemented for the type `sdl2::surface::Surface<'_>`
    //(&maze_surface as &sdl2_image::SaveSurface).save(&Path::new("./maze_render.png")).expect("Failed to save surface as PNG");
    maze_surface.save_bmp(&Path::new("./maze_render.bmp")).expect("Failed to save surface as BMP");

    let screen_texture = renderer.create_texture_from_surface(maze_surface).unwrap();

    let mut events = sdl_setup.sdl_context.event_pump().unwrap();
    'running: loop {
        for event in events.poll_iter() {
            match event {
                Event::Quit{..} => break 'running,
                Event::KeyDown{keycode: Some(sdl2::keyboard::Keycode::Q), ..} => break 'running,
                _ => continue,

                // handle redrawing the texture when the windows gets bigger and can show more?
            }
        }

        renderer.set_draw_color(WHITE);
        renderer.clear();
        renderer.copy(&screen_texture, None, None);
        renderer.present();
    }
}

fn draw_maze<GridIndexType>(r: &mut Renderer, grid: &SquareGrid<GridIndexType>)
    where GridIndexType: IndexType
{
    // clear the texture background to white
    r.set_draw_color(WHITE);
    r.clear();

    // Set the maze wall colour.
    r.set_draw_color(BLUE);

    let cell_size_pixels = 10;
    let img_width = cell_size_pixels * grid.dimension();  // usize usize
    let img_height = cell_size_pixels * grid.dimension();
    let (max_width, max_height) = match r.logical_size() { (w, h) => (w as usize, h as usize) };

    let x_centering_offset = if img_width  < max_width { (max_width - img_width)/2 } else { 0 };
    let y_centering_offset = if img_height < max_height { (max_height - img_height)/2 } else { 0 };

    for cell in grid.iter() {
        let column = cell.x as usize;
        let row = cell.y as usize;

        let x1 = ((column * cell_size_pixels) + x_centering_offset) as i32;
        let y1 = ((row * cell_size_pixels) + y_centering_offset) as i32;
        let x2 = (((column + 1) * cell_size_pixels) + x_centering_offset) as i32;
        let y2 = (((row + 1) * cell_size_pixels) + y_centering_offset) as i32;

        // special cases north and west to handle first row and column.
        if grid.neighbour_at_direction(&cell, GridDirection::North).is_none() {
            r.draw_line(Point::new(x1, y1), Point::new(x2, y1)).unwrap();
        }
        if grid.neighbour_at_direction(&cell, GridDirection::West).is_none() {
            r.draw_line(Point::new(x1, y1), Point::new(x1, y2)).unwrap();
        }

        if !grid.is_neighbour_linked(&cell, GridDirection::East) {
            r.draw_line(Point::new(x2, y1), Point::new(x2, y2)).unwrap();
        }
        if !grid.is_neighbour_linked(&cell, GridDirection::South) {
            r.draw_line(Point::new(x1, y2), Point::new(x2, y2)).unwrap();
        }
    }
}

fn draw_maze_to_texture<GridIndexType>(r: &mut Renderer,
                                       t: Texture,
                                       grid: &SquareGrid<GridIndexType>)
                                       -> Texture
    where GridIndexType: IndexType
{
    // Setup to draw to the given texture. The texture is moved/owned by the `set` call.
    r.render_target()
     .expect("This platform doesn't support render targets")
     .set(t).unwrap(); // Returns the old render target if the function is successful, which we ignore.

    draw_maze(r, &grid);

    // Reseting gives us back ownership of the updated texture and restores the default render target
    let updated_texture: Option<Texture> = r.render_target().unwrap().reset().unwrap();
    updated_texture.unwrap()
}

//// Research Notes
//
// For a non-text based view of a maze we need a GUI window if
// we want to see anything live.
// To just write out an image we only need an sdl surface
// to draw on and write out as a PNG?
// Renderer seems to require a window...though the window
// could be hidden I guess?
// - sdl_context -> video_subsystem -> window_builder
// - window_builder options:
//   - *hidden*, fullscreen, opengl enabled, borderless, resizable
//
// sdl2_image provides:
// trait SaveSurface for Surface (save as PNG only)
// trait LoadSurface for Surface (load any texture)
// trait LoadTexture for Renderer
//
// sdl2 provides a Surface accessor on the Renderer type, which
// may also work even if the Renderer is using a Texture?
// I'm guessing that *all* renderers for a window have a Surface, but
// textures as memory locations on the GPU are optional.
// SDL_Surface is just a collection of pixels while SDL_Texture is an
// efficient, driver-specific representation of pixel data
// SDL_Texture on the other hand, is used in a hardware rendering, textures
// are stored in VRAM and you don't have access to it directly as with SDL_Surface.
// The rendering operations are accelerated by GPU, using, internally, either
// OpenGL or DirectX (available only on Windows) API, which in turn are using
// your video hardware, hence hardware rendering name.
// http://stackoverflow.com/questions/21007329/what-is-a-sdl-renderer/21007477#21007477
//
// Actually the section "If your game just wants to get fully-rendered frames to the screen"
// looks like what we want: https://wiki.libsdl.org/MigrationGuide
//
// should we use rendererbuilder target_texture? "Set the renderer to support rendering to a texture."
// does that mean we can render to a texture then do whatever.... renderer.create_texture_target
// renderer. render_target(&mut self) -> Option<RenderTarget>
// When the render target has been set/created the draw_line/fill_rect etc calls are directed to that
// render target.
//
// # drawing every pixel yourself in software and then doing one big blit (software doom etc.)
// - single sdlTexture to represent the screen
// - texture access streaming (frequent content change of the texture)
// - create surface or [u8] as RGBA buffer block of pixels (can convert if need to from other formats)
// - sdl_updatetexture (texture.update) at the end which uploads the pixels to the gpu.
// - [SDL_RenderSetLogicalSize()] so we get scaling as required.
// - render clear
// - rendercopy sdlTexture (put the texture on the gpu in to the backbuffer/framebuffer memory)
// - render present
// Examples:
// - https://github.com/AngryLawyer/rust-sdl2/blob/master/examples/renderer-texture.rs shows streaming texture
//   but does not draw any lines, just messes with a mutable [u8] buffer.
//
// # blitting multiple "sprites" to the screen (treating surfaces as sprites, not pixel buffers)
//   textures tend to be static once uploaded
// - create texture(s) one per sprite etc. +
// - texture access static
// (or createTextureFromSurface as these two steps)
// (it's annoying that the rust api makes it hard to draw a line to a surface)
//
// # Blit surfaces and modify individual pixels in the framebuffer.
//   Round trips--reading data back from textures--can be painfully expensive; generally you want to be pushing data in one direction always.
//   You are probably best off, in this case, keeping everything in software until the final push to the screen, so we'll combine the two previous techniques.
//  - create 'screen' texture
//  - create screen surface
//  - compose the final framebuffer into the sdl_surface.
//  - update texture from screen surface
//  - render clear && render copy 'screen' texture && render present
// N.B.
// SDL_TEXTUREACCESS_STATIC changes rarely, not lockable
// SDL_TEXTUREACCESS_STREAMING changes frequently, lockable
// SDL_TEXTUREACCESS_TARGET can be used as a render target
// Static textures are designed for sprites and backgrounds and other images that don't change much.
// You update them with pixels using SDL_UpdateTexture() (which is pretty slow compared to streaming).
// ```
// let static_maze_texture = renderer.create_texture_static(PixelFormatEnum::RGB888, LOGICAL_W, LOGICAL_H).unwrap();
// Surface::new(...)
// data = surface.without_lock() -> Option<&[u8]> to get the pixel data
// static_maze_texture.update(..., data)
// ```
// Streaming textures are designed for things that update frequently, every few seconds, or every frame.
// You can also update them with SDL_UpdateTexture(), but for optimal performance you lock them, write the pixels,
// and then unlock them.
// Presumably locking allows you to write to them on the GPU directly as you 'stream' the data into them, whereas
// updateTexture just blats the whole thing.
//
// If the renderer is in fullscreen desktop mode we wouldn't know or care what the size
// is but we could then SDL_RenderSetLogicalSize(sdlRenderer, 640, 480); for example.
// The app works with a given logical size but sdl scales it on the GPU, even handling scaling
// with different aspect ratios and letterboxing the difference.
<|endoftext|>


<commit_before>//! Treat an [`OffsetDateTime`] as a [Unix timestamp] for the purposes of serde.
//!
//! Use this module in combination with serde's [`#[with]`][with] attribute.
//!
//! When deserializing, the offset is assumed to be UTC.
//!
//! ```rust
//! # use time::{OffsetDateTime, macros::datetime};
//! # use serde_json::json;
//! # use serde::{Serialize, Deserialize};
//! #[derive(Debug, PartialEq, Serialize, Deserialize)]
//! struct S {
//!     #[serde(with = "time::serde::timestamp")]
//!     datetime: OffsetDateTime,
//! }
//!
//! let s = S {
//!     datetime: datetime!("2019-01-01 0:00 UTC"),
//! };
//! let v = json!({ "datetime": 1_546_300_800 });
//! assert_eq!(v, serde_json::to_value(&s)?);
//! assert_eq!(s, serde_json::from_value(v)?);
//! # Ok::<_, serde_json::Error>(())
//! ```
//!
//! [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
//! [with]: https://serde.rs/field-attrs.html#with

use crate::{error::ComponentRange, OffsetDateTime};
use serde::{Deserialize, Deserializer, Serialize, Serializer};

/// Serialize an `OffsetDateTime` as its Unix timestamp
pub fn serialize<S: Serializer>(
    datetime: &OffsetDateTime,
    serializer: S,
) -> Result<S::Ok, S::Error> {
    datetime.unix_timestamp().serialize(serializer)
}

/// Deserialize an `OffsetDateTime` from its Unix timestamp
pub fn deserialize<'a, D: Deserializer<'a>>(deserializer: D) -> Result<OffsetDateTime, D::Error> {
    i64::deserialize(deserializer).and_then(|timestamp| {
        OffsetDateTime::from_unix_timestamp(timestamp)
            .map_err(ComponentRange::to_invalid_serde_value::<D>)
    })
}

/// Treat an `Option<OffsetDateTime>` as a [Unix timestamp] for the purposes of
/// serde.
///
/// Use this module in combination with serde's [`#[with]`][with] attribute.
///
/// When deserializing, the offset is assumed to be UTC.
///
/// ```rust
/// # use time::{OffsetDateTime, macros::datetime};
/// # use serde_json::json;
/// # use serde::{Serialize, Deserialize};
/// #[derive(Debug, PartialEq, Serialize, Deserialize)]
/// struct S {
///     #[serde(with = "time::serde::timestamp::option")]
///     datetime: Option<OffsetDateTime>,
/// }
///
/// let s = S {
///     datetime: Some(datetime!("2019-01-01 0:00 UTC")),
/// };
/// let v = json!({ "datetime": 1_546_300_800 });
/// assert_eq!(v, serde_json::to_value(&s)?);
/// assert_eq!(s, serde_json::from_value(v)?);
///
/// let s = S { datetime: None };
/// let v = json!({ "datetime": null });
/// assert_eq!(v, serde_json::to_value(&s)?);
/// assert_eq!(s, serde_json::from_value(v)?);
/// # Ok::<_, serde_json::Error>(())
/// ```
///
/// [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
/// [with]: https://serde.rs/field-attrs.html#with
pub mod option {
    #[allow(clippy::wildcard_imports)]
    use super::*;

    /// Serialize an `Option<OffsetDateTime>` as its Unix timestamp
    pub fn serialize<S: Serializer>(
        option: &Option<OffsetDateTime>,
        serializer: S,
    ) -> Result<S::Ok, S::Error> {
        option
            .map(OffsetDateTime::unix_timestamp)
            .serialize(serializer)
    }

    /// Deserialize an `Option<OffsetDateTime>` from its Unix timestamp
    pub fn deserialize<'a, D: Deserializer<'a>>(
        deserializer: D,
    ) -> Result<Option<OffsetDateTime>, D::Error> {
        Option::deserialize(deserializer)?
            .map(OffsetDateTime::from_unix_timestamp)
            .transpose()
            .map_err(ComponentRange::to_invalid_serde_value::<D>)
    }
}
<commit_msg>Remove doctests that use removed dependency<commit_after>//! Treat an [`OffsetDateTime`] as a [Unix timestamp] for the purposes of serde.
//!
//! Use this module in combination with serde's [`#[with]`][with] attribute.
//!
//! When deserializing, the offset is assumed to be UTC.
//!
//! [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
//! [with]: https://serde.rs/field-attrs.html#with

use crate::{error::ComponentRange, OffsetDateTime};
use serde::{Deserialize, Deserializer, Serialize, Serializer};

/// Serialize an `OffsetDateTime` as its Unix timestamp
pub fn serialize<S: Serializer>(
    datetime: &OffsetDateTime,
    serializer: S,
) -> Result<S::Ok, S::Error> {
    datetime.unix_timestamp().serialize(serializer)
}

/// Deserialize an `OffsetDateTime` from its Unix timestamp
pub fn deserialize<'a, D: Deserializer<'a>>(deserializer: D) -> Result<OffsetDateTime, D::Error> {
    i64::deserialize(deserializer).and_then(|timestamp| {
        OffsetDateTime::from_unix_timestamp(timestamp)
            .map_err(ComponentRange::to_invalid_serde_value::<D>)
    })
}

/// Treat an `Option<OffsetDateTime>` as a [Unix timestamp] for the purposes of
/// serde.
///
/// Use this module in combination with serde's [`#[with]`][with] attribute.
///
/// When deserializing, the offset is assumed to be UTC.
///
/// [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
/// [with]: https://serde.rs/field-attrs.html#with
pub mod option {
    #[allow(clippy::wildcard_imports)]
    use super::*;

    /// Serialize an `Option<OffsetDateTime>` as its Unix timestamp
    pub fn serialize<S: Serializer>(
        option: &Option<OffsetDateTime>,
        serializer: S,
    ) -> Result<S::Ok, S::Error> {
        option
            .map(OffsetDateTime::unix_timestamp)
            .serialize(serializer)
    }

    /// Deserialize an `Option<OffsetDateTime>` from its Unix timestamp
    pub fn deserialize<'a, D: Deserializer<'a>>(
        deserializer: D,
    ) -> Result<Option<OffsetDateTime>, D::Error> {
        Option::deserialize(deserializer)?
            .map(OffsetDateTime::from_unix_timestamp)
            .transpose()
            .map_err(ComponentRange::to_invalid_serde_value::<D>)
    }
}
<|endoftext|>