<commit_before>extern crate core;
use self::core::ops::DerefMut;

use super::connection::{Connection, ReleaseNameReply, DO_NOT_QUEUE};
use super::error::Error;
use super::interface::Interfaces;
use super::message::{Message, MessageType};
use super::object::Object;
use super::target::Target;

use std::cell::RefCell;
use std::collections::btree_map::{BTreeMap, Entry};
use std::rc::Rc;

type SignalHandler = Rc<RefCell<FnMut(&Connection, &Target) -> ()>>;
type SignalHandlers = Vec<SignalHandler>;
type SignalHandlerMap = BTreeMap<Target, SignalHandlers>;

fn _add_handler(handlers: &mut SignalHandlerMap, signal: Target, handler: SignalHandler) {
    match handlers.entry(signal) {
        Entry::Vacant(v)    => { v.insert(vec![handler]); },
        Entry::Occupied(o)  => o.into_mut().push(handler),
    };
}

pub struct Server {
    conn: Rc<Connection>,
    name: String,
    can_handle: bool,

    // TODO: store children information
    objects: BTreeMap<String, Object>,
    signals: SignalHandlerMap,
    namespace_signals: SignalHandlerMap,
}

impl Server {
    pub fn new_listener(conn: Rc<Connection>, name: &str) -> Result<Self, Error> {
        Ok(Server {
            conn: conn,
            name: name.to_owned(),
            can_handle: false,

            objects: BTreeMap::new(),
            signals: BTreeMap::new(),
            namespace_signals: BTreeMap::new(),
        })
    }

    pub fn new(conn: Rc<Connection>, name: &str) -> Result<Self, Error> {
        try!(conn.request_name(name, DO_NOT_QUEUE));

        // TODO: Add match for the server.
        // TODO: add root object
        // TODO: add ObjectManager interface

        Ok(Server {
            conn: conn,
            name: name.to_owned(),
            can_handle: true,

            objects: BTreeMap::new(),
            signals: BTreeMap::new(),
            namespace_signals: BTreeMap::new(),
        })
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn add_object(&mut self, path: &str, iface_map: Interfaces) -> Result<&mut Self, Error> {
        if !self.can_handle {
            return Err(Error::NoServerName);
        }

        // TODO: Validate the path is valid.

        match self.objects.entry(path.to_owned()) {
            Entry::Vacant(v)    => {
                // TODO: store this
                let children = Rc::new(RefCell::new(vec![]));
                let obj = try!(Object::new(path, iface_map, children));

                // TODO: emit InterfacesAdded signal

                v.insert(obj);

                Ok(())
            },
            Entry::Occupied(_)  => Err(Error::PathAlreadyRegistered(path.to_owned())),
        }.map(|_| self)
    }

    pub fn remove_object(&mut self, path: &str) -> Result<&mut Self, Error> {
        if !self.can_handle {
            return Err(Error::NoServerName);
        }

        match self.objects.remove(path) {
            Some(_) => {
                // TODO: emit InterfacesRemoved signal

                Ok(self)
            },
            None    => Err(Error::NoSuchPath(path.to_owned())),
        }
    }

    pub fn connect<F>(&mut self, signal: Target, callback: F) -> Result<&mut Self, Error>
        where F: FnMut(&Connection, &Target) -> () + 'static {
        let dbus_match = format!("type='signal',interface='{}',path='{}',member='{}'",
                                 signal.interface,
                                 signal.object,
                                 signal.method);
        try!(self.conn.add_match(&dbus_match));

        _add_handler(&mut self.signals, signal, Rc::new(RefCell::new(callback)));

        Ok(self)
    }

    pub fn connect_namespace<F>(&mut self, signal: Target, callback: F) -> Result<&mut Self, Error>
        where F: FnMut(&Connection, &Target) -> () + 'static {
        let dbus_match = format!("type='signal',interface='{}',path_namespace='{}',member='{}'",
                                 signal.interface,
                                 signal.object,
                                 signal.method);
        try!(self.conn.add_match(&dbus_match));

        _add_handler(&mut self.namespace_signals, signal, Rc::new(RefCell::new(callback)));

        Ok(self)
    }

    pub fn handle_message<'b>(&self, m: &'b mut Message) -> Option<&'b mut Message> {
        match m.message_type() {
            MessageType::MethodCall => self._call_method(m),
            MessageType::Signal     => Some(self._match_signal(m)),
            _                       => Some(m),
        }
    }

    fn _call_method<'b>(&self, m: &'b mut Message) -> Option<&'b mut Message> {
        let conn = self.conn.clone();
        self.objects.iter().fold(Some(m), |opt_m, (_, object)| {
            opt_m.and_then(|mut m| {
                match object.handle_message(&conn, &mut m) {
                    None          => Some(m),
                    Some(Ok(()))  => None,
                    Some(Err(())) => {
                        println!("failed to send a reply for {:?}", m);
                        None
                    },
                }
            })
        })
    }

    fn _match_signal<'b>(&self, m: &'b mut Message) -> &'b mut Message {
        let conn = self.conn.clone();

        Target::extract(m).map(|signal| {
            for handlers in self.signals.get(&signal) {
                for handler in handlers.iter() {
                    let mut cb = handler.borrow_mut();

                    cb.deref_mut()(&conn, &signal);
                }
            }

            let matched_handlers = self.namespace_signals.iter().filter(|&(expect, _)| {
                expect.namespace_eq(&signal)
            });

            for (_, handlers) in matched_handlers {
                for handler in handlers.iter() {
                    let mut cb = handler.borrow_mut();

                    cb.deref_mut()(&conn, &signal);
                };
            };
        });

        m
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        if !self.can_handle {
            return;
        }

        let res = self.conn.release_name(&self.name);
        match res {
            Ok(reply) =>
                match reply {
                    ReleaseNameReply::Released    => (),
                    ReleaseNameReply::NonExistent => panic!("internal error: non-existent name {}?!", self.name),
                    ReleaseNameReply::NotOwner    => panic!("internal error: not the owner of {}?!", self.name),
                },
            Err(err) => println!("failed to release {}: {:?}", self.name, err),
        }
    }
}
<commit_msg>server: rename Interfaces parameter<commit_after>extern crate core;
use self::core::ops::DerefMut;

use super::connection::{Connection, ReleaseNameReply, DO_NOT_QUEUE};
use super::error::Error;
use super::interface::Interfaces;
use super::message::{Message, MessageType};
use super::object::Object;
use super::target::Target;

use std::cell::RefCell;
use std::collections::btree_map::{BTreeMap, Entry};
use std::rc::Rc;

type SignalHandler = Rc<RefCell<FnMut(&Connection, &Target) -> ()>>;
type SignalHandlers = Vec<SignalHandler>;
type SignalHandlerMap = BTreeMap<Target, SignalHandlers>;

fn _add_handler(handlers: &mut SignalHandlerMap, signal: Target, handler: SignalHandler) {
    match handlers.entry(signal) {
        Entry::Vacant(v)    => { v.insert(vec![handler]); },
        Entry::Occupied(o)  => o.into_mut().push(handler),
    };
}

pub struct Server {
    conn: Rc<Connection>,
    name: String,
    can_handle: bool,

    // TODO: store children information
    objects: BTreeMap<String, Object>,
    signals: SignalHandlerMap,
    namespace_signals: SignalHandlerMap,
}

impl Server {
    pub fn new_listener(conn: Rc<Connection>, name: &str) -> Result<Self, Error> {
        Ok(Server {
            conn: conn,
            name: name.to_owned(),
            can_handle: false,

            objects: BTreeMap::new(),
            signals: BTreeMap::new(),
            namespace_signals: BTreeMap::new(),
        })
    }

    pub fn new(conn: Rc<Connection>, name: &str) -> Result<Self, Error> {
        try!(conn.request_name(name, DO_NOT_QUEUE));

        // TODO: Add match for the server.
        // TODO: add root object
        // TODO: add ObjectManager interface

        Ok(Server {
            conn: conn,
            name: name.to_owned(),
            can_handle: true,

            objects: BTreeMap::new(),
            signals: BTreeMap::new(),
            namespace_signals: BTreeMap::new(),
        })
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn add_object(&mut self, path: &str, ifaces: Interfaces) -> Result<&mut Self, Error> {
        if !self.can_handle {
            return Err(Error::NoServerName);
        }

        // TODO: Validate the path is valid.

        match self.objects.entry(path.to_owned()) {
            Entry::Vacant(v)    => {
                // TODO: store this
                let children = Rc::new(RefCell::new(vec![]));
                let obj = try!(Object::new(path, ifaces, children));

                // TODO: emit InterfacesAdded signal

                v.insert(obj);

                Ok(())
            },
            Entry::Occupied(_)  => Err(Error::PathAlreadyRegistered(path.to_owned())),
        }.map(|_| self)
    }

    pub fn remove_object(&mut self, path: &str) -> Result<&mut Self, Error> {
        if !self.can_handle {
            return Err(Error::NoServerName);
        }

        match self.objects.remove(path) {
            Some(_) => {
                // TODO: emit InterfacesRemoved signal

                Ok(self)
            },
            None    => Err(Error::NoSuchPath(path.to_owned())),
        }
    }

    pub fn connect<F>(&mut self, signal: Target, callback: F) -> Result<&mut Self, Error>
        where F: FnMut(&Connection, &Target) -> () + 'static {
        let dbus_match = format!("type='signal',interface='{}',path='{}',member='{}'",
                                 signal.interface,
                                 signal.object,
                                 signal.method);
        try!(self.conn.add_match(&dbus_match));

        _add_handler(&mut self.signals, signal, Rc::new(RefCell::new(callback)));

        Ok(self)
    }

    pub fn connect_namespace<F>(&mut self, signal: Target, callback: F) -> Result<&mut Self, Error>
        where F: FnMut(&Connection, &Target) -> () + 'static {
        let dbus_match = format!("type='signal',interface='{}',path_namespace='{}',member='{}'",
                                 signal.interface,
                                 signal.object,
                                 signal.method);
        try!(self.conn.add_match(&dbus_match));

        _add_handler(&mut self.namespace_signals, signal, Rc::new(RefCell::new(callback)));

        Ok(self)
    }

    pub fn handle_message<'b>(&self, m: &'b mut Message) -> Option<&'b mut Message> {
        match m.message_type() {
            MessageType::MethodCall => self._call_method(m),
            MessageType::Signal     => Some(self._match_signal(m)),
            _                       => Some(m),
        }
    }

    fn _call_method<'b>(&self, m: &'b mut Message) -> Option<&'b mut Message> {
        let conn = self.conn.clone();
        self.objects.iter().fold(Some(m), |opt_m, (_, object)| {
            opt_m.and_then(|mut m| {
                match object.handle_message(&conn, &mut m) {
                    None          => Some(m),
                    Some(Ok(()))  => None,
                    Some(Err(())) => {
                        println!("failed to send a reply for {:?}", m);
                        None
                    },
                }
            })
        })
    }

    fn _match_signal<'b>(&self, m: &'b mut Message) -> &'b mut Message {
        let conn = self.conn.clone();

        Target::extract(m).map(|signal| {
            for handlers in self.signals.get(&signal) {
                for handler in handlers.iter() {
                    let mut cb = handler.borrow_mut();

                    cb.deref_mut()(&conn, &signal);
                }
            }

            let matched_handlers = self.namespace_signals.iter().filter(|&(expect, _)| {
                expect.namespace_eq(&signal)
            });

            for (_, handlers) in matched_handlers {
                for handler in handlers.iter() {
                    let mut cb = handler.borrow_mut();

                    cb.deref_mut()(&conn, &signal);
                };
            };
        });

        m
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        if !self.can_handle {
            return;
        }

        let res = self.conn.release_name(&self.name);
        match res {
            Ok(reply) =>
                match reply {
                    ReleaseNameReply::Released    => (),
                    ReleaseNameReply::NonExistent => panic!("internal error: non-existent name {}?!", self.name),
                    ReleaseNameReply::NotOwner    => panic!("internal error: not the owner of {}?!", self.name),
                },
            Err(err) => println!("failed to release {}: {:?}", self.name, err),
        }
    }
}
<|endoftext|>


<commit_before>use grain_capnp::{PowerboxCapability, UiView, UiSession};
use web_session_capnp::{WebSession};

use capnp::capability::{ClientHook, FromServer};
use capnp::AnyPointer;
use capnp_rpc::rpc::{RpcConnectionState, SturdyRefRestorer};
use capnp_rpc::capability::{LocalClient};

pub struct UiViewImpl;

impl PowerboxCapability::Server for UiViewImpl {
    fn get_powerbox_info(&mut self, context : PowerboxCapability::GetPowerboxInfoContext) {
        context.done()
    }
}

impl UiView::Server for UiViewImpl {
    fn get_view_info(&mut self, context : UiView::GetViewInfoContext) {
        context.done()
    }

    fn new_session(&mut self, mut context : UiView::NewSessionContext) {
        println!("asked for a new session!");
        let (_, results) = context.get();

        let client : WebSession::Client = FromServer::new(None::<LocalClient>, ~WebSessionImpl);
        // we need to do this dance to upcast.
        results.set_session(UiSession::Client { client : client.client});

        context.done()
    }
}

pub struct WebSessionImpl;

impl UiSession::Server for WebSessionImpl {

}

static main_css : &'static str =
    "body { font-family: Helvetica, Sans, Arial;
            font-size: medium;
             margin-left: auto;
             margin-right: auto;
             width: 600px;
     }";

static header : &'static str =
  r#"<title> acronymy </title><link rel="stylesheet" type="text/css" href="main.css" >
 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
  "#;

impl WebSession::Server for WebSessionImpl {
    fn get(&mut self, mut context : WebSession::GetContext) {
        println!("GET");
        let (params, results) = context.get();
        let path = params.get_path();
        println!("path = {}", path);
        let content = results.init_content();
        content.set_mime_type("text/html");
        if path == "main.css" {
            content.get_body().set_bytes(main_css.as_bytes())
        } else {
            content.get_body().set_bytes(
                format!("{}<form action=\"define\" method=\"get\"><input name=\"word\"/><button>go</button></form>",
                        header).as_bytes());
        }
        context.done()
    }
    fn post(&mut self, context : WebSession::PostContext) {
        println!("POST");
        context.done()
    }
    fn put(&mut self, context : WebSession::PutContext) {
        println!("PUT");
        context.done()
    }
    fn delete(&mut self, context : WebSession::DeleteContext) {
        println!("DELETE");
        context.done()
    }
    fn open_web_socket(&mut self, context : WebSession::OpenWebSocketContext) {
        println!("OPEN WEB SOCKET");
        context.done()
    }
}

pub struct FdStream {
    inner : ~::std::rt::rtio::RtioFileStream:Send,
}

impl FdStream {
    pub fn new(fd : ::libc::c_int) -> ::std::io::IoResult<FdStream> {
        ::std::rt::rtio::LocalIo::maybe_raise(|io| {
            Ok (FdStream { inner : io.fs_from_raw_fd(fd, ::std::rt::rtio::DontClose) })
        })
    }
}

impl Reader for FdStream {
    fn read(&mut self, buf : &mut [u8]) -> ::std::io::IoResult<uint> {
        self.inner.read(buf).map(|i| i as uint)
    }
}

impl Writer for FdStream {
    fn write(&mut self, buf : &[u8]) -> ::std::io::IoResult<()> {
        self.inner.write(buf)
    }
}

pub struct Restorer;

impl SturdyRefRestorer for Restorer {
    fn restore(&self, obj_id : AnyPointer::Reader) -> Option<~ClientHook:Send> {
        if obj_id.is_null() {
            let client : UiView::Client = FromServer::new(None::<LocalClient>, ~UiViewImpl);
            Some(client.client.hook)
        } else {
            None
        }
    }
}

pub fn main() -> ::std::io::IoResult<()> {
    let ifs = try!(FdStream::new(3));
    let ofs = try!(FdStream::new(3));

    let connection_state = RpcConnectionState::new();
    connection_state.run(ifs, ofs, Restorer);

    Ok(())
}

<commit_msg>path parsing<commit_after>use grain_capnp::{PowerboxCapability, UiView, UiSession};
use web_session_capnp::{WebSession};

use capnp::capability::{ClientHook, FromServer};
use capnp::AnyPointer;
use capnp_rpc::rpc::{RpcConnectionState, SturdyRefRestorer};
use capnp_rpc::capability::{LocalClient};

pub struct UiViewImpl;

impl PowerboxCapability::Server for UiViewImpl {
    fn get_powerbox_info(&mut self, context : PowerboxCapability::GetPowerboxInfoContext) {
        context.done()
    }
}

impl UiView::Server for UiViewImpl {
    fn get_view_info(&mut self, context : UiView::GetViewInfoContext) {
        context.done()
    }

    fn new_session(&mut self, mut context : UiView::NewSessionContext) {
        println!("asked for a new session!");
        let (_, results) = context.get();

        let client : WebSession::Client = FromServer::new(None::<LocalClient>, ~WebSessionImpl);
        // we need to do this dance to upcast.
        results.set_session(UiSession::Client { client : client.client});

        context.done()
    }
}

pub struct WebSessionImpl;

impl UiSession::Server for WebSessionImpl {

}

static main_css : &'static str =
    "body { font-family: Helvetica, Sans, Arial;
            font-size: medium;
             margin-left: auto;
             margin-right: auto;
             width: 600px;
     }";

static header : &'static str =
  r#"<title> acronymy </title><link rel="stylesheet" type="text/css" href="main.css" >
 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
  "#;

fn html_body(body :&str) -> ~str {
    format!("{}{}", header, body)
}

struct Path {
    path : ~str,
    query : Vec<(~str,Vec<~str>)>,
}

impl Path {
    fn new() -> Path {
        Path { path : ~"", query : Vec::new() }
    }
}

fn parse_path(path : &str) -> Path {
    let mut result = Path::new();

    let v : ~[&str] = path.splitn('?', 2).collect();
    if v.len() == 0 {
        return result;
    }
    if v.len() == 1 {
        result.path = v[0].into_owned();
    }
    for attr in v[1].split('&') {
        let a : ~[&str] = attr.splitn('=', 2).collect();
        if a.len() == 2 {
            result.query.push((a[0].into_owned(),
                               a[1].split('+').map(|s| {s.into_owned() }).collect()));
        }
    }
    return result;
}

impl WebSession::Server for WebSessionImpl {
    fn get(&mut self, mut context : WebSession::GetContext) {
        println!("GET");
        let (params, results) = context.get();
        let raw_path = params.get_path();
        println!("path = {}", raw_path);
        let content = results.init_content();
        content.set_mime_type("text/html");

        let path = parse_path(raw_path);
        if raw_path == "main.css" {
            content.get_body().set_bytes(main_css.as_bytes())
        } else if path.path.as_slice() == "define" {
            content.get_body().set_bytes("AWESOME".as_bytes());
        } else {
            content.get_body().set_bytes(
                html_body(
                    "<form action=\"define\" method=\"get\">
                     <input name=\"word\"/><button>go</button></form>").as_bytes());
        }
        context.done()
    }
    fn post(&mut self, context : WebSession::PostContext) {
        println!("POST");
        context.done()
    }
    fn put(&mut self, context : WebSession::PutContext) {
        println!("PUT");
        context.done()
    }
    fn delete(&mut self, context : WebSession::DeleteContext) {
        println!("DELETE");
        context.done()
    }
    fn open_web_socket(&mut self, context : WebSession::OpenWebSocketContext) {
        println!("OPEN WEB SOCKET");
        context.done()
    }
}

pub struct FdStream {
    inner : ~::std::rt::rtio::RtioFileStream:Send,
}

impl FdStream {
    pub fn new(fd : ::libc::c_int) -> ::std::io::IoResult<FdStream> {
        ::std::rt::rtio::LocalIo::maybe_raise(|io| {
            Ok (FdStream { inner : io.fs_from_raw_fd(fd, ::std::rt::rtio::DontClose) })
        })
    }
}

impl Reader for FdStream {
    fn read(&mut self, buf : &mut [u8]) -> ::std::io::IoResult<uint> {
        self.inner.read(buf).map(|i| i as uint)
    }
}

impl Writer for FdStream {
    fn write(&mut self, buf : &[u8]) -> ::std::io::IoResult<()> {
        self.inner.write(buf)
    }
}

pub struct Restorer;

impl SturdyRefRestorer for Restorer {
    fn restore(&self, obj_id : AnyPointer::Reader) -> Option<~ClientHook:Send> {
        if obj_id.is_null() {
            let client : UiView::Client = FromServer::new(None::<LocalClient>, ~UiViewImpl);
            Some(client.client.hook)
        } else {
            None
        }
    }
}

pub fn main() -> ::std::io::IoResult<()> {
    let ifs = try!(FdStream::new(3));
    let ofs = try!(FdStream::new(3));

    let connection_state = RpcConnectionState::new();
    connection_state.run(ifs, ofs, Restorer);

    Ok(())
}

<|endoftext|>


<commit_before>extern crate http;
extern crate time;

use std::vec::Vec;

use std::io::net::ip::{SocketAddr, Ipv4Addr};
use std::io::Writer;

use http::server::{Config, Server, Request, ResponseWriter};
use http::headers;

mod app;

#[deriving(Clone)]
pub struct EVReserve;

impl http::server::Server for EVReserve {
    fn get_config(&self) -> Config {
        Config { bind_address: SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 8001 } }
    }

    fn handle_request(&self, _r: &Request, w: &mut ResponseWriter) {
        let content = app::get_content();
        let content_bytes = content.get_bytes();
        w.headers.date = Some(time::now_utc());
        w.headers.server = Some(~"Apache/2.2.22 (Ubuntu)");
        //w.headers.last_modified = Some(~"Thu, 05 May 2011 11:46:42 GMT");
        w.headers.last_modified = Some(time::Tm {
            tm_sec: 42, // seconds after the minute ~[0-60]
            tm_min: 46, // minutes after the hour ~[0-59]
            tm_hour: 11, // hours after midnight ~[0-23]
            tm_mday: 5, // days of the month ~[1-31]
            tm_mon: 4, // months since January ~[0-11]
            tm_year: 111, // years since 1900
            tm_wday: 4, // days since Sunday ~[0-6]
            tm_yday: 0, // days since January 1 ~[0-365]
            tm_isdst: 0, // Daylight Savings Time flag
            tm_gmtoff: 0, // offset from UTC in seconds
            tm_zone: ~"GMT", // timezone abbreviation
            tm_nsec: 0, // nanoseconds
        });
        w.headers.etag = Some(headers::etag::EntityTag {
                                weak: false,
                                opaque_tag: ~"501b29-b1-4a285ed47404a" });
        w.headers.accept_ranges = Some(headers::accept_ranges::RangeUnits(
                                            vec!(headers::accept_ranges::Bytes)));
        w.headers.content_length = Some(content_bytes.len());
        w.headers.vary = Some(~"Accept-Encoding");
        w.headers.content_type = Some(headers::content_type::MediaType {
            type_: ~"text",
            subtype: ~"html",
            parameters: Vec::new()
        });
        w.headers.extensions.insert(~"X-Pad", ~"avoid browser bug");

        w.write(content_bytes).unwrap();
    }
}

<commit_msg>get_bytes() -> as_bytes()<commit_after>extern crate http;
extern crate time;

use std::vec::Vec;

use std::io::net::ip::{SocketAddr, Ipv4Addr};
use std::io::Writer;

use http::server::{Config, Server, Request, ResponseWriter};
use http::headers;

mod app;

#[deriving(Clone)]
pub struct EVReserve;

impl http::server::Server for EVReserve {
    fn get_config(&self) -> Config {
        Config { bind_address: SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 8001 } }
    }

    fn handle_request(&self, _r: &Request, w: &mut ResponseWriter) {
        let content = app::get_content();
        let content_bytes = content.as_bytes();
        w.headers.date = Some(time::now_utc());
        w.headers.server = Some(~"Apache/2.2.22 (Ubuntu)");
        //w.headers.last_modified = Some(~"Thu, 05 May 2011 11:46:42 GMT");
        w.headers.last_modified = Some(time::Tm {
            tm_sec: 42, // seconds after the minute ~[0-60]
            tm_min: 46, // minutes after the hour ~[0-59]
            tm_hour: 11, // hours after midnight ~[0-23]
            tm_mday: 5, // days of the month ~[1-31]
            tm_mon: 4, // months since January ~[0-11]
            tm_year: 111, // years since 1900
            tm_wday: 4, // days since Sunday ~[0-6]
            tm_yday: 0, // days since January 1 ~[0-365]
            tm_isdst: 0, // Daylight Savings Time flag
            tm_gmtoff: 0, // offset from UTC in seconds
            tm_zone: ~"GMT", // timezone abbreviation
            tm_nsec: 0, // nanoseconds
        });
        w.headers.etag = Some(headers::etag::EntityTag {
                                weak: false,
                                opaque_tag: ~"501b29-b1-4a285ed47404a" });
        w.headers.accept_ranges = Some(headers::accept_ranges::RangeUnits(
                                            vec!(headers::accept_ranges::Bytes)));
        w.headers.content_length = Some(content_bytes.len());
        w.headers.vary = Some(~"Accept-Encoding");
        w.headers.content_type = Some(headers::content_type::MediaType {
            type_: ~"text",
            subtype: ~"html",
            parameters: Vec::new()
        });
        w.headers.extensions.insert(~"X-Pad", ~"avoid browser bug");

        w.write(content_bytes).unwrap();
    }
}

<|endoftext|>


<commit_before>use luminance::{FragmentShader, GeometryShader, StageError, ShaderTypeable,
                TessellationControlShader, TessellationEvaluationShader, VertexShader};
use luminance_gl::gl33::{ProgramProxy, Stage};
#[cfg(feature = "hot-shader")]
use notify::{self, RecommendedWatcher, Watcher};
#[cfg(feature = "hot-shader")]
use std::collections::BTreeMap;
use std::fs;
use std::io::Read;
#[cfg(not(feature = "hot-shader"))]
use std::marker::PhantomData;
use std::ops::Deref;
use std::path::PathBuf;
#[cfg(feature = "hot-shader")]
use std::sync::{Arc, Mutex};
#[cfg(feature = "hot-shader")]
use std::sync::mpsc;
#[cfg(feature = "hot-shader")]
use std::thread;

pub use luminance::{ProgramError, UniformUpdate};
pub use luminance_gl::gl33::{Program, Uniform};

#[derive(Debug)]
pub enum ShaderError {
  StageError(StageError),
  ProgramError(ProgramError)
}

fn compile_stages(tess_src: Option<(&str, &str)>, vs_src: &str, gs_src: Option<&str>, fs_src: &str) -> Result<(Option<(Stage<TessellationControlShader>, Stage<TessellationEvaluationShader>)>, Stage<VertexShader>, Option<Stage<GeometryShader>>, Stage<FragmentShader>), StageError> {
  let tess = match tess_src {
    None => None,
    Some((tcs_src, tes_src)) => {
      let tcs = try!(Stage::new(tcs_src));
      let tes = try!(Stage::new(tes_src));
      Some((tcs, tes))
    }
  };
  let vs = try!(Stage::new(vs_src));
  let gs = match gs_src {
    None => None,
    Some(gs_src) => {
      let gs = try!(Stage::new(gs_src));
      Some(gs)
    }
  };
  let fs = try!(Stage::new(fs_src));

  Ok((tess, vs, gs, fs))
}

pub fn new_program<GetUni, T>(tess_src: Option<(&str, &str)>, vs_src: &str, gs_src: Option<&str>, fs_src: &str, get_uni: &GetUni) -> Result<Program<T>, ProgramError> where GetUni: Fn(ProgramProxy) -> Result<T, ProgramError> {
  let stages = compile_stages(tess_src, vs_src, gs_src, fs_src);

  match stages {
    Ok((tess, vs, gs, fs)) => {
      if let Some((tcs, tes)) = tess {
        if let Some(gs) = gs {
          Program::new(Some((&tcs, &tes)), &vs, Some(&gs), &fs, get_uni)
        } else {
          Program::new(Some((&tcs, &tes)), &vs, None, &fs, get_uni)
        }
      } else {
        if let Some(gs) = gs {
          Program::new(None, &vs, Some(&gs), &fs, get_uni)
        } else {
          Program::new(None, &vs, None, &fs, get_uni)
        }
      }
    },
    Err(stage_error) => {
      Err(ProgramError::LinkFailed(format!("{:?}", stage_error)))
    }
  }
}

pub fn new_program_from_disk<GetUni, T>(tess_path: Option<(PathBuf, PathBuf)>, vs_path: PathBuf, gs_path: Option<PathBuf>, fs_path: PathBuf, get_uni: &GetUni) -> Result<Program<T>, ProgramError>
      where GetUni: Fn(ProgramProxy) -> Result<T, ProgramError> {
  // load vertex and fragment shaders first
  let vs = try!(read_stage(vs_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
  let fs = try!(read_stage(fs_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));

  match (tess_path, gs_path) {
    (None, None) => { // no tessellation nor geometry
      Program::new(None, &vs, None, &fs, get_uni)
    },
    (Some((tcs_path, tes_path)), None) => { // tessellation without geometry
      let tcs = try!(read_stage(tcs_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
      let tes = try!(read_stage(tes_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
      Program::new(Some((&tcs, &tes)), &vs, None, &fs, get_uni)
    },
    (None, Some(gs_path)) => { // geometry without tessellation
      let gs = try!(read_stage(gs_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
      Program::new(None, &vs, Some(&gs), &fs, get_uni)
    },
    (Some((tcs_path, tes_path)), Some(gs_path)) => { // tessellation and geometry
      let tcs = try!(read_stage(tcs_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
      let tes = try!(read_stage(tes_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
      let gs = try!(read_stage(gs_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
      Program::new(Some((&tcs, &tes)), &vs, Some(&gs), &fs, get_uni)
    }
  }
}

pub fn read_stage<T>(path: PathBuf) -> Result<Stage<T>, StageError> where T: ShaderTypeable {
  info!("\tloading {:?} stage: \x1b[35m{:?}", T::shader_type(), path);

  let fh = fs::File::open(path);

  match fh {
    Err(e) => {
      Err(StageError::CompilationFailed(T::shader_type(), format!("{:?}", e)))
    },
    Ok(mut fh) => {
      let mut stage_src = String::new();
      let _ = fh.read_to_string(&mut stage_src);

      Stage::new(stage_src.chars().as_str())
    }
  }
}

/// Shader builder.
#[cfg(feature = "hot-shader")]
pub struct ProgramBuilder {
  watcher: RecommendedWatcher,
  receivers: Arc<Mutex<BTreeMap<PathBuf, mpsc::Sender<()>>>>
}
#[cfg(not(feature = "hot-shader"))]
pub struct ProgramBuilder {}

#[cfg(feature = "hot-shader")]
impl ProgramBuilder {
  pub fn new(shader_root: PathBuf) -> Self {
    let (wsx, wrx) = mpsc::channel();
    let mut watcher: RecommendedWatcher = Watcher::new(wsx).unwrap();
    let receivers: Arc<Mutex<BTreeMap<PathBuf, mpsc::Sender<()>>>> = Arc::new(Mutex::new(BTreeMap::new()));

    let _ = watcher.watch(shader_root);

    let receivers_ = receivers.clone();
    let _ = thread::spawn(move || {
      for event in wrx.iter() {
        match event {
          notify::Event { path: Some(path), op: Ok(notify::op::WRITE) } => {
            if let Some(sx) = receivers_.lock().unwrap().get(&path) {
              sx.send(()).unwrap();
            }
          },
          _ => {}
        }
      }
    });

    ProgramBuilder {
      watcher: watcher,
      receivers: receivers
    }
  }

  pub fn retrieve<'a, T, GetUni>(&mut self, tess_path: Option<(PathBuf, PathBuf)>, vs_path: PathBuf, gs_path: Option<PathBuf>, fs_path: PathBuf, get_uni: GetUni) -> Result<WrappedProgram<'a, T>, ProgramError>
      where GetUni: 'a + Fn(ProgramProxy) -> Result<T, ProgramError> {
    let program = try!(new_program_from_disk(tess_path.clone(), vs_path.clone(), gs_path.clone(), fs_path.clone(), &get_uni));
    let (sx, rx) = mpsc::channel();

    self.monitor_shader(tess_path.clone(), vs_path.clone(), gs_path.clone(), fs_path.clone(), sx);

    Ok(WrappedProgram {
      rx: rx,
      program: program,
      get_uni: Box::new(get_uni),
      vs_path: vs_path,
      fs_path: fs_path,
      tess_path: tess_path,
      gs_path: gs_path,
    })
  }

  /// Add surveillance of a given `Program` by providing the path to all its shaders. When a change
  /// occurs, the `Program` gets notified of the change via its `Receiver` channel part.
  fn monitor_shader(&mut self, tess: Option<(PathBuf, PathBuf)>, vs: PathBuf, gs: Option<PathBuf>, fs: PathBuf, sx: mpsc::Sender<()>) {
    let mut receivers = self.receivers.lock().unwrap();

    // vertex shader
    receivers.insert(vs, sx.clone());

    // fragment shader
    receivers.insert(fs, sx.clone());

    // tessellation, if needed
    if let Some((tcs, tes)) = tess {
      // tessellation control shader
      receivers.insert(tcs, sx.clone());
      // tessellation evaluation shader
      receivers.insert(tes, sx.clone());
    }

    // geometry shader, if needed
    if let Some(gs) = gs {
      receivers.insert(gs, sx.clone());
    }
  }
}
#[cfg(not(feature = "hot-shader"))]
impl ProgramBuilder {
  pub fn new(_: PathBuf) -> Self {
    ProgramBuilder {}
  }

  pub fn retrieve<'a, T, GetUni>(&mut self, tess_path: Option<(PathBuf, PathBuf)>, vs_path: PathBuf, gs_path: Option<PathBuf>, fs_path: PathBuf, get_uni: GetUni) -> Result<WrappedProgram<'a, T>, ProgramError>
      where GetUni: 'a + Fn(ProgramProxy) -> Result<T, ProgramError> {
    let program = try!(new_program_from_disk(tess_path, vs_path, gs_path, fs_path, &get_uni));

    Ok(WrappedProgram {
      program: program,
      _a: PhantomData
    })
  }
}

/// A `Program` wrapped by **ion**.
///
/// That wrapper is used to enable hot-reloading of shader programs.
#[cfg(feature = "hot-shader")]
pub struct WrappedProgram<'a, T> {
  rx: mpsc::Receiver<()>,
  program: Program<T>,
  get_uni: Box<Fn(ProgramProxy) -> Result<T, ProgramError> + 'a>,
  vs_path: PathBuf,
  fs_path: PathBuf,
  tess_path: Option<(PathBuf, PathBuf)>,
  gs_path: Option<PathBuf>
}
#[cfg(not(feature = "hot-shader"))]
pub struct WrappedProgram<'a, T> {
  program: Program<T>,
  _a: PhantomData<&'a ()>
}

impl<'a, T> WrappedProgram<'a, T> {
  #[cfg(feature = "hot-shader")]
  fn reload(&mut self) {
    let program = new_program_from_disk(self.tess_path.clone(), self.vs_path.clone(), self.gs_path.clone(), self.fs_path.clone(), &self.get_uni.as_ref());

    match program {
      Ok(program) => {
        self.program = program;
      },
      Err(err) => {
        warn!("reloading program has failed: {:?}", err);
      }
    }
  }

  /// Sync the embedded `Program`.
  #[cfg(feature = "hot-shader")]
  pub fn sync(&mut self) {
    if self.rx.try_recv().is_ok() {
      self.reload();
    }
  }
  #[cfg(not(feature = "hot-shader"))]
  pub fn sync(&mut self) {}
}

impl<'a, T> Deref for WrappedProgram<'a, T> {
  type Target = Program<T>;

  fn deref(&self) -> &Self::Target {
    &self.program
  }
}
<commit_msg>Removed \t in shader loader debug messages (it was annoying).<commit_after>use luminance::{FragmentShader, GeometryShader, StageError, ShaderTypeable,
                TessellationControlShader, TessellationEvaluationShader, VertexShader};
use luminance_gl::gl33::{ProgramProxy, Stage};
#[cfg(feature = "hot-shader")]
use notify::{self, RecommendedWatcher, Watcher};
#[cfg(feature = "hot-shader")]
use std::collections::BTreeMap;
use std::fs;
use std::io::Read;
#[cfg(not(feature = "hot-shader"))]
use std::marker::PhantomData;
use std::ops::Deref;
use std::path::PathBuf;
#[cfg(feature = "hot-shader")]
use std::sync::{Arc, Mutex};
#[cfg(feature = "hot-shader")]
use std::sync::mpsc;
#[cfg(feature = "hot-shader")]
use std::thread;

pub use luminance::{ProgramError, UniformUpdate};
pub use luminance_gl::gl33::{Program, Uniform};

#[derive(Debug)]
pub enum ShaderError {
  StageError(StageError),
  ProgramError(ProgramError)
}

fn compile_stages(tess_src: Option<(&str, &str)>, vs_src: &str, gs_src: Option<&str>, fs_src: &str) -> Result<(Option<(Stage<TessellationControlShader>, Stage<TessellationEvaluationShader>)>, Stage<VertexShader>, Option<Stage<GeometryShader>>, Stage<FragmentShader>), StageError> {
  let tess = match tess_src {
    None => None,
    Some((tcs_src, tes_src)) => {
      let tcs = try!(Stage::new(tcs_src));
      let tes = try!(Stage::new(tes_src));
      Some((tcs, tes))
    }
  };
  let vs = try!(Stage::new(vs_src));
  let gs = match gs_src {
    None => None,
    Some(gs_src) => {
      let gs = try!(Stage::new(gs_src));
      Some(gs)
    }
  };
  let fs = try!(Stage::new(fs_src));

  Ok((tess, vs, gs, fs))
}

pub fn new_program<GetUni, T>(tess_src: Option<(&str, &str)>, vs_src: &str, gs_src: Option<&str>, fs_src: &str, get_uni: &GetUni) -> Result<Program<T>, ProgramError> where GetUni: Fn(ProgramProxy) -> Result<T, ProgramError> {
  let stages = compile_stages(tess_src, vs_src, gs_src, fs_src);

  match stages {
    Ok((tess, vs, gs, fs)) => {
      if let Some((tcs, tes)) = tess {
        if let Some(gs) = gs {
          Program::new(Some((&tcs, &tes)), &vs, Some(&gs), &fs, get_uni)
        } else {
          Program::new(Some((&tcs, &tes)), &vs, None, &fs, get_uni)
        }
      } else {
        if let Some(gs) = gs {
          Program::new(None, &vs, Some(&gs), &fs, get_uni)
        } else {
          Program::new(None, &vs, None, &fs, get_uni)
        }
      }
    },
    Err(stage_error) => {
      Err(ProgramError::LinkFailed(format!("{:?}", stage_error)))
    }
  }
}

pub fn new_program_from_disk<GetUni, T>(tess_path: Option<(PathBuf, PathBuf)>, vs_path: PathBuf, gs_path: Option<PathBuf>, fs_path: PathBuf, get_uni: &GetUni) -> Result<Program<T>, ProgramError>
      where GetUni: Fn(ProgramProxy) -> Result<T, ProgramError> {
  // load vertex and fragment shaders first
  let vs = try!(read_stage(vs_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
  let fs = try!(read_stage(fs_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));

  match (tess_path, gs_path) {
    (None, None) => { // no tessellation nor geometry
      Program::new(None, &vs, None, &fs, get_uni)
    },
    (Some((tcs_path, tes_path)), None) => { // tessellation without geometry
      let tcs = try!(read_stage(tcs_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
      let tes = try!(read_stage(tes_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
      Program::new(Some((&tcs, &tes)), &vs, None, &fs, get_uni)
    },
    (None, Some(gs_path)) => { // geometry without tessellation
      let gs = try!(read_stage(gs_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
      Program::new(None, &vs, Some(&gs), &fs, get_uni)
    },
    (Some((tcs_path, tes_path)), Some(gs_path)) => { // tessellation and geometry
      let tcs = try!(read_stage(tcs_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
      let tes = try!(read_stage(tes_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
      let gs = try!(read_stage(gs_path).map_err(|e| ProgramError::LinkFailed(format!("{:?}", e))));
      Program::new(Some((&tcs, &tes)), &vs, Some(&gs), &fs, get_uni)
    }
  }
}

pub fn read_stage<T>(path: PathBuf) -> Result<Stage<T>, StageError> where T: ShaderTypeable {
  info!("loading {:?} stage: \x1b[35m{:?}", T::shader_type(), path);

  let fh = fs::File::open(path);

  match fh {
    Err(e) => {
      Err(StageError::CompilationFailed(T::shader_type(), format!("{:?}", e)))
    },
    Ok(mut fh) => {
      let mut stage_src = String::new();
      let _ = fh.read_to_string(&mut stage_src);

      Stage::new(stage_src.chars().as_str())
    }
  }
}

/// Shader builder.
#[cfg(feature = "hot-shader")]
pub struct ProgramBuilder {
  watcher: RecommendedWatcher,
  receivers: Arc<Mutex<BTreeMap<PathBuf, mpsc::Sender<()>>>>
}
#[cfg(not(feature = "hot-shader"))]
pub struct ProgramBuilder {}

#[cfg(feature = "hot-shader")]
impl ProgramBuilder {
  pub fn new(shader_root: PathBuf) -> Self {
    let (wsx, wrx) = mpsc::channel();
    let mut watcher: RecommendedWatcher = Watcher::new(wsx).unwrap();
    let receivers: Arc<Mutex<BTreeMap<PathBuf, mpsc::Sender<()>>>> = Arc::new(Mutex::new(BTreeMap::new()));

    let _ = watcher.watch(shader_root);

    let receivers_ = receivers.clone();
    let _ = thread::spawn(move || {
      for event in wrx.iter() {
        match event {
          notify::Event { path: Some(path), op: Ok(notify::op::WRITE) } => {
            if let Some(sx) = receivers_.lock().unwrap().get(&path) {
              sx.send(()).unwrap();
            }
          },
          _ => {}
        }
      }
    });

    ProgramBuilder {
      watcher: watcher,
      receivers: receivers
    }
  }

  pub fn retrieve<'a, T, GetUni>(&mut self, tess_path: Option<(PathBuf, PathBuf)>, vs_path: PathBuf, gs_path: Option<PathBuf>, fs_path: PathBuf, get_uni: GetUni) -> Result<WrappedProgram<'a, T>, ProgramError>
      where GetUni: 'a + Fn(ProgramProxy) -> Result<T, ProgramError> {
    let program = try!(new_program_from_disk(tess_path.clone(), vs_path.clone(), gs_path.clone(), fs_path.clone(), &get_uni));
    let (sx, rx) = mpsc::channel();

    self.monitor_shader(tess_path.clone(), vs_path.clone(), gs_path.clone(), fs_path.clone(), sx);

    Ok(WrappedProgram {
      rx: rx,
      program: program,
      get_uni: Box::new(get_uni),
      vs_path: vs_path,
      fs_path: fs_path,
      tess_path: tess_path,
      gs_path: gs_path,
    })
  }

  /// Add surveillance of a given `Program` by providing the path to all its shaders. When a change
  /// occurs, the `Program` gets notified of the change via its `Receiver` channel part.
  fn monitor_shader(&mut self, tess: Option<(PathBuf, PathBuf)>, vs: PathBuf, gs: Option<PathBuf>, fs: PathBuf, sx: mpsc::Sender<()>) {
    let mut receivers = self.receivers.lock().unwrap();

    // vertex shader
    receivers.insert(vs, sx.clone());

    // fragment shader
    receivers.insert(fs, sx.clone());

    // tessellation, if needed
    if let Some((tcs, tes)) = tess {
      // tessellation control shader
      receivers.insert(tcs, sx.clone());
      // tessellation evaluation shader
      receivers.insert(tes, sx.clone());
    }

    // geometry shader, if needed
    if let Some(gs) = gs {
      receivers.insert(gs, sx.clone());
    }
  }
}
#[cfg(not(feature = "hot-shader"))]
impl ProgramBuilder {
  pub fn new(_: PathBuf) -> Self {
    ProgramBuilder {}
  }

  pub fn retrieve<'a, T, GetUni>(&mut self, tess_path: Option<(PathBuf, PathBuf)>, vs_path: PathBuf, gs_path: Option<PathBuf>, fs_path: PathBuf, get_uni: GetUni) -> Result<WrappedProgram<'a, T>, ProgramError>
      where GetUni: 'a + Fn(ProgramProxy) -> Result<T, ProgramError> {
    let program = try!(new_program_from_disk(tess_path, vs_path, gs_path, fs_path, &get_uni));

    Ok(WrappedProgram {
      program: program,
      _a: PhantomData
    })
  }
}

/// A `Program` wrapped by **ion**.
///
/// That wrapper is used to enable hot-reloading of shader programs.
#[cfg(feature = "hot-shader")]
pub struct WrappedProgram<'a, T> {
  rx: mpsc::Receiver<()>,
  program: Program<T>,
  get_uni: Box<Fn(ProgramProxy) -> Result<T, ProgramError> + 'a>,
  vs_path: PathBuf,
  fs_path: PathBuf,
  tess_path: Option<(PathBuf, PathBuf)>,
  gs_path: Option<PathBuf>
}
#[cfg(not(feature = "hot-shader"))]
pub struct WrappedProgram<'a, T> {
  program: Program<T>,
  _a: PhantomData<&'a ()>
}

impl<'a, T> WrappedProgram<'a, T> {
  #[cfg(feature = "hot-shader")]
  fn reload(&mut self) {
    let program = new_program_from_disk(self.tess_path.clone(), self.vs_path.clone(), self.gs_path.clone(), self.fs_path.clone(), &self.get_uni.as_ref());

    match program {
      Ok(program) => {
        self.program = program;
      },
      Err(err) => {
        warn!("reloading program has failed: {:?}", err);
      }
    }
  }

  /// Sync the embedded `Program`.
  #[cfg(feature = "hot-shader")]
  pub fn sync(&mut self) {
    if self.rx.try_recv().is_ok() {
      self.reload();
    }
  }
  #[cfg(not(feature = "hot-shader"))]
  pub fn sync(&mut self) {}
}

impl<'a, T> Deref for WrappedProgram<'a, T> {
  type Target = Program<T>;

  fn deref(&self) -> &Self::Target {
    &self.program
  }
}
<|endoftext|>


<commit_before>//! Fundamental traits for ODE

use ndarray::*;
use ndarray_linalg::*;

pub trait ModelSize<D: Dimension> {
    fn model_size(&self) -> D::Pattern;
}

/// Interface for time-step
pub trait TimeStep {
    type Time: RealScalar;
    fn get_dt(&self) -> Self::Time;
    fn set_dt(&mut self, dt: Self::Time);
}

/// Equation of motion (Explicit)
pub trait Explicit<D: Dimension>: ModelSize<D> {
    type Scalar: Scalar;
    type Time: RealScalar;
    /// calculate right hand side (rhs) of Explicit from current state
    fn rhs<S>(&self, &mut ArrayBase<S, D>) where S: DataMut<Elem = Self::Scalar>;
}

pub trait SemiImplicit<D: Dimension>: ModelSize<D> {
    type Scalar: Scalar;
    type Time: RealScalar;
    /// non-linear part of stiff equation
    fn nlin<S>(&self, &mut ArrayBase<S, D>) where S: DataMut<Elem = Self::Scalar>;
}

/// Time-evolution operator with buffer
pub trait TimeEvolution<D: Dimension>: ModelSize<D> + TimeStep {
    type Scalar: Scalar;
    type Buffer;
    /// calculate next step
    fn iterate<S>(&self, &mut ArrayBase<S, D>, &mut Buffer) where S: DataMut<Elem = Self::Scalar>;
}
<commit_msg>Add new_buffer<commit_after>//! Fundamental traits for ODE

use ndarray::*;
use ndarray_linalg::*;

pub trait ModelSize<D: Dimension> {
    fn model_size(&self) -> D::Pattern;
}

/// Interface for time-step
pub trait TimeStep {
    type Time: RealScalar;
    fn get_dt(&self) -> Self::Time;
    fn set_dt(&mut self, dt: Self::Time);
}

/// Equation of motion (Explicit)
pub trait Explicit<D: Dimension>: ModelSize<D> {
    type Scalar: Scalar;
    type Time: RealScalar;
    /// calculate right hand side (rhs) of Explicit from current state
    fn rhs<S>(&self, &mut ArrayBase<S, D>) where S: DataMut<Elem = Self::Scalar>;
}

pub trait SemiImplicit<D: Dimension>: ModelSize<D> {
    type Scalar: Scalar;
    type Time: RealScalar;
    /// non-linear part of stiff equation
    fn nlin<S>(&self, &mut ArrayBase<S, D>) where S: DataMut<Elem = Self::Scalar>;
}

/// Time-evolution operator with buffer
pub trait TimeEvolution<D: Dimension>: ModelSize<D> + TimeStep {
    type Scalar: Scalar;
    type Buffer;
    /// Generate new calculate buffer
    fn new_buffer(&self) -> Self::Buffer;
    /// calculate next step
    fn iterate<S>(&self, &mut ArrayBase<S, D>, &mut Self::Buffer)
        where S: DataMut<Elem = Self::Scalar>;
}
<|endoftext|>


<commit_before>use std::ffi::CString;
use std::fmt;
use std::io::{IoResult, IoError, File, Open, ReadWrite};
use std::os::unix::prelude::AsRawFd;
use libc::c_int;
use libc::consts::os::bsd44::{AF_INET6, SOCK_DGRAM};
use libc::funcs::bsd43::socket;
use libc::funcs::bsd44::ioctl;
use libc::funcs::posix88::unistd::close;
use libc::types::os::common::bsd44::in6_addr;
use c_interop::*;

const DEVICE_PATH: &'static str = "/dev/net/tun";

// TODO Make not a constant
const MTU_SIZE: usize = 1500;

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum TunTapType {
	Tun,
	Tap
}

pub struct TunTap {
	pub file: File,
	sock: c_int,
	if_name: [u8; IFNAMSIZ],
	if_index: c_int
}

impl Drop for TunTap {
	fn drop(&mut self) {
		unsafe { close(self.sock) };
	}
}

impl fmt::Debug for TunTap {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Tun({:?})", self.get_name())
	}
}

impl TunTap {
	pub fn create(typ: TunTapType) -> TunTap {
		TunTap::create_named(typ, &CString::from_slice(&[]))
	}

	pub fn create_named(typ: TunTapType, name: &CString) -> TunTap {
		let (file, if_name) = TunTap::create_if(typ, name);
		let (sock, if_index) = TunTap::create_socket(if_name);

		TunTap {
			file: file,
			sock: sock,
			if_name: if_name,
			if_index: if_index
		}
	}

	fn create_if(typ: TunTapType, name: &CString) -> (File, [u8; IFNAMSIZ]) {
		let name_slice = name.as_bytes_with_nul();
		if name_slice.len() > IFNAMSIZ {
			panic!("Interface name too long, max length is {}", IFNAMSIZ - 1);
		}

		let path = Path::new(DEVICE_PATH);
		let file = match File::open_mode(&path, Open, ReadWrite) {
			Err(why) => panic!("Couldn't open tun device '{}': {}", path.display(), why.desc),
			Ok(file) => file,
		};

		let mut req = ioctl_flags_data {
			ifr_name: {
				let mut buffer = [0u8; IFNAMSIZ];
				buffer.clone_from_slice(name_slice);
				buffer
			},
			ifr_flags: match typ {
				TunTapType::Tun => IFF_TUN,
				TunTapType::Tap => IFF_TAP
			}
		};

		let res = unsafe { ioctl(file.as_raw_fd(), TUNSETIFF, &mut req) };
		if res < 0 {
			panic!("{}", IoError::last_error());
		}

		(file, req.ifr_name)
	}

	fn create_socket(if_name: [u8; IFNAMSIZ]) -> (c_int, c_int) {
		let sock = unsafe { socket(AF_INET6, SOCK_DGRAM, 0) };
		if sock < 0 {
			panic!("{}", IoError::last_error());
		}

		let mut req = ioctl_ifindex_data {
			ifr_name: if_name,
			ifr_ifindex: -1
		};

		let res = unsafe { ioctl(sock, SIOCGIFINDEX, &mut req) };
		if res < 0 {
			let err = IoError::last_error();
			unsafe { close(sock) };
			panic!("{}", err);
		}

		(sock, req.ifr_ifindex)
	}

	pub fn get_name(&self) -> CString {
		let nul_pos = match self.if_name.as_slice().position_elem(&0) {
			Some(p) => p,
			None => panic!("Device name should be null-terminated")
		};

		CString::from_slice(self.if_name.slice_to(nul_pos))
	}

	pub fn up(&self) {
		let mut req = ioctl_flags_data {
			ifr_name: self.if_name,
			ifr_flags: 0
		};

		let res = unsafe { ioctl(self.sock, SIOCGIFFLAGS, &mut req) };
		if res < 0 {
			panic!("{}", IoError::last_error());
		}

		if req.ifr_flags & IFF_UP & IFF_RUNNING != 0 {
			// Already up
			return;
		}

		req.ifr_flags |= IFF_UP | IFF_RUNNING;

		let res = unsafe { ioctl(self.sock, SIOCSIFFLAGS, &mut req) };
		if res < 0 {
			panic!("{}", IoError::last_error());
		}
	}

	pub fn add_address(&self, ip: &[u8]) {
		self.up();

		if ip.len() == 4 {
			panic!("IPv4 not implemented");
		}
		else if ip.len() == 16 {
			let mut req = in6_ifreq {
				ifr6_addr: in6_addr {s6_addr: [
					(ip[ 1] as u16) << 8 | ip[ 0] as u16,
					(ip[ 3] as u16) << 8 | ip[ 2] as u16,
					(ip[ 5] as u16) << 8 | ip[ 4] as u16,
					(ip[ 7] as u16) << 8 | ip[ 6] as u16,
					(ip[ 9] as u16) << 8 | ip[ 8] as u16,
					(ip[11] as u16) << 8 | ip[10] as u16,
					(ip[13] as u16) << 8 | ip[12] as u16,
					(ip[15] as u16) << 8 | ip[14] as u16
				]},
				ifr6_prefixlen: 8,
				ifr6_ifindex: self.if_index
			};

			let res = unsafe { ioctl(self.sock, SIOCSIFADDR, &mut req) };
			if res < 0 {
				panic!("{}", IoError::last_error());
			}
		}
		else {
			panic!("IP length must be either 4 or 16 bytes, got {}", ip.len());
		}
	}

	pub fn read<'a>(&mut self, buffer: &'a mut [u8]) -> IoResult<&'a [u8]> {
		assert!(buffer.len() >= MTU_SIZE);

		let len = try!(self.file.read(buffer));
		Ok(buffer.slice_to(len))
	}

	pub fn write(&mut self, data: &[u8]) -> IoResult<()> {
		self.file.write(data)
	}
}
<commit_msg>Slice syntax fallout<commit_after>use std::ffi::CString;
use std::fmt;
use std::io::{IoResult, IoError, File, Open, ReadWrite};
use std::os::unix::prelude::AsRawFd;
use libc::c_int;
use libc::consts::os::bsd44::{AF_INET6, SOCK_DGRAM};
use libc::funcs::bsd43::socket;
use libc::funcs::bsd44::ioctl;
use libc::funcs::posix88::unistd::close;
use libc::types::os::common::bsd44::in6_addr;
use c_interop::*;

const DEVICE_PATH: &'static str = "/dev/net/tun";

// TODO Make not a constant
const MTU_SIZE: usize = 1500;

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum TunTapType {
	Tun,
	Tap
}

pub struct TunTap {
	pub file: File,
	sock: c_int,
	if_name: [u8; IFNAMSIZ],
	if_index: c_int
}

impl Drop for TunTap {
	fn drop(&mut self) {
		unsafe { close(self.sock) };
	}
}

impl fmt::Debug for TunTap {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Tun({:?})", self.get_name())
	}
}

impl TunTap {
	pub fn create(typ: TunTapType) -> TunTap {
		TunTap::create_named(typ, &CString::from_slice(&[]))
	}

	pub fn create_named(typ: TunTapType, name: &CString) -> TunTap {
		let (file, if_name) = TunTap::create_if(typ, name);
		let (sock, if_index) = TunTap::create_socket(if_name);

		TunTap {
			file: file,
			sock: sock,
			if_name: if_name,
			if_index: if_index
		}
	}

	fn create_if(typ: TunTapType, name: &CString) -> (File, [u8; IFNAMSIZ]) {
		let name_slice = name.as_bytes_with_nul();
		if name_slice.len() > IFNAMSIZ {
			panic!("Interface name too long, max length is {}", IFNAMSIZ - 1);
		}

		let path = Path::new(DEVICE_PATH);
		let file = match File::open_mode(&path, Open, ReadWrite) {
			Err(why) => panic!("Couldn't open tun device '{}': {}", path.display(), why.desc),
			Ok(file) => file,
		};

		let mut req = ioctl_flags_data {
			ifr_name: {
				let mut buffer = [0u8; IFNAMSIZ];
				buffer.clone_from_slice(name_slice);
				buffer
			},
			ifr_flags: match typ {
				TunTapType::Tun => IFF_TUN,
				TunTapType::Tap => IFF_TAP
			}
		};

		let res = unsafe { ioctl(file.as_raw_fd(), TUNSETIFF, &mut req) };
		if res < 0 {
			panic!("{}", IoError::last_error());
		}

		(file, req.ifr_name)
	}

	fn create_socket(if_name: [u8; IFNAMSIZ]) -> (c_int, c_int) {
		let sock = unsafe { socket(AF_INET6, SOCK_DGRAM, 0) };
		if sock < 0 {
			panic!("{}", IoError::last_error());
		}

		let mut req = ioctl_ifindex_data {
			ifr_name: if_name,
			ifr_ifindex: -1
		};

		let res = unsafe { ioctl(sock, SIOCGIFINDEX, &mut req) };
		if res < 0 {
			let err = IoError::last_error();
			unsafe { close(sock) };
			panic!("{}", err);
		}

		(sock, req.ifr_ifindex)
	}

	pub fn get_name(&self) -> CString {
		let nul_pos = match self.if_name.as_slice().position_elem(&0) {
			Some(p) => p,
			None => panic!("Device name should be null-terminated")
		};

		CString::from_slice(&self.if_name[..nul_pos])
	}

	pub fn up(&self) {
		let mut req = ioctl_flags_data {
			ifr_name: self.if_name,
			ifr_flags: 0
		};

		let res = unsafe { ioctl(self.sock, SIOCGIFFLAGS, &mut req) };
		if res < 0 {
			panic!("{}", IoError::last_error());
		}

		if req.ifr_flags & IFF_UP & IFF_RUNNING != 0 {
			// Already up
			return;
		}

		req.ifr_flags |= IFF_UP | IFF_RUNNING;

		let res = unsafe { ioctl(self.sock, SIOCSIFFLAGS, &mut req) };
		if res < 0 {
			panic!("{}", IoError::last_error());
		}
	}

	pub fn add_address(&self, ip: &[u8]) {
		self.up();

		if ip.len() == 4 {
			panic!("IPv4 not implemented");
		}
		else if ip.len() == 16 {
			let mut req = in6_ifreq {
				ifr6_addr: in6_addr {s6_addr: [
					(ip[ 1] as u16) << 8 | ip[ 0] as u16,
					(ip[ 3] as u16) << 8 | ip[ 2] as u16,
					(ip[ 5] as u16) << 8 | ip[ 4] as u16,
					(ip[ 7] as u16) << 8 | ip[ 6] as u16,
					(ip[ 9] as u16) << 8 | ip[ 8] as u16,
					(ip[11] as u16) << 8 | ip[10] as u16,
					(ip[13] as u16) << 8 | ip[12] as u16,
					(ip[15] as u16) << 8 | ip[14] as u16
				]},
				ifr6_prefixlen: 8,
				ifr6_ifindex: self.if_index
			};

			let res = unsafe { ioctl(self.sock, SIOCSIFADDR, &mut req) };
			if res < 0 {
				panic!("{}", IoError::last_error());
			}
		}
		else {
			panic!("IP length must be either 4 or 16 bytes, got {}", ip.len());
		}
	}

	pub fn read<'a>(&mut self, buffer: &'a mut [u8]) -> IoResult<&'a [u8]> {
		assert!(buffer.len() >= MTU_SIZE);

		let len = try!(self.file.read(buffer));
		Ok(&buffer[..len])
	}

	pub fn write(&mut self, data: &[u8]) -> IoResult<()> {
		self.file.write(data)
	}
}
<|endoftext|>


<commit_before>//!
//! Values manipulated by endpoints
//!

use std::time::Duration;
use std::cmp::{PartialOrd, Ordering};

extern crate chrono;
use self::chrono::{DateTime, Local};

extern crate serde_json;

///
/// The type of values manipulated by endpoints.
///
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub enum Type {
    ///
    /// # Trivial values
    ///

    /// An empty value. Used for instance to inform that a countdown
    /// has reached 0 or that a device is ready.
    Unit,

    /// A boolean. Used for instance for on-off switches, presence
    /// detectors, etc.
    Bool,

    ///
    /// # Time
    ///

    /// A duration. Used for instance in countdowns.
    Duration,

    /// A precise timestamp. Used for instance to determine when an
    /// event has taken place.
    TimeStamp,

    Temperature,

    ///
    /// ...
    ///
    Color,
    Json,
    Binary,
    ExtNumeric,
}

/// A temperature. Internal representation may be either Fahrenheit or
/// Celcius. The FoxBox adapters are expected to perform conversions
/// to the format requested by their devices.
#[derive(Debug, Clone, PartialEq)]
pub enum Temperature {
    /// Fahrenheit
    F(f64),
    /// Celcius
    C(f64),
}

impl Temperature {
    /// Get a temperature in Fahrenheit.
    pub fn as_f(&self) -> f64 {
        unimplemented!();
    }

    /// Get a temperature in Celcius.
    pub fn as_c(&self) -> f64 {
        unimplemented!();
    }
}

impl PartialOrd for Temperature {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_c().partial_cmp(&other.as_c())
    }
}

/// A color. Internal representation may vary. The FoxBox adapters are
/// expected to perform conversions to the format requested by their
/// device.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum Color {
    RGBA(f64, f64, f64, f64, f64)
}

/// Representation of an object in JSON. It is often (albeit not
/// always) possible to choose a more precise data structure for
/// representing values send/accepted by a service. If possible,
/// adapters should rather pick such more precise data structure.
#[derive(Debug, Clone, PartialEq)]
pub struct Json(serde_json::value::Value);

impl PartialOrd for Json {
    /// Two Json objects are never comparable to each other.
    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
        None
    }
}

/// A data structure holding a numeric value of a type that has not
/// been standardized yet.
#[derive(Debug, Clone, PartialEq)]
pub struct ExtNumeric {
    value: f64,

    /// The vendor. Used for namespacing purposes, to avoid
    /// confusing two incompatible extensions with similar
    /// names. For instance, "foxlink@mozilla.com".
    vendor: String,

    /// Identification of the adapter introducing this value.
    /// Designed to aid with tracing and debugging.
    adapter: String,

    /// A string describing the nature of the value, designed to
    /// aid with type-checking.
    ///
    /// Examples: `"GroundHumidity"`.
    kind: String,
}

impl PartialOrd for ExtNumeric {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.vendor != other.vendor {
            return None;
        } else if self.kind != other.kind {
            return None;
        } else {
            self.value.partial_cmp(&other.value)
        }
    }
}

/// Base definitions for actual values. Most API clients will rather
/// use `Value`.
///
/// Splitting the defintion between `Value` and `ValueBase` is mostly
/// a convenience to refine the automatically-derived `PartialOrd` on
/// `ValueBase` into something that will never compare two values with
/// different types.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum ValueBase {
    Unit,
    Bool(bool),
    Duration(Duration),
    TimeStamp(chrono::DateTime<Local>),
    Temperature(Temperature),
    Color(Color),

    // FIXME: Add more as we identify needs

    /// A numeric value representing a unit that has not been
    /// standardized yet into the API.
    ExtNumeric(ExtNumeric),
    Json(Json),
    Binary {data: Vec<u8>, mimetype: String}
}

impl ValueBase {
    pub fn get_type(&self) -> Type {
        match *self {
            ValueBase::Unit => Type::Unit,
            ValueBase::Bool(_) => Type::Bool,
            ValueBase::Duration(_) => Type::Duration,
            ValueBase::TimeStamp(_) => Type::TimeStamp,
            ValueBase::Temperature(_) => Type::Temperature,
            ValueBase::Color(_) => Type::Color,
            ValueBase::Json(_) => Type::Json,
            ValueBase::Binary{..} => Type::Binary,
            ValueBase::ExtNumeric(_) => Type::ExtNumeric,
        }
    }
}

/// Representation of an actual value that can be sent to/received
/// from a service.
#[derive(Debug, Clone, PartialEq)]
pub struct Value(ValueBase);

impl Value {
    /// Get the type attached to a value.
    pub fn get_type(&self) -> Type {
        self.0.get_type()
    }
}

impl PartialOrd for Value {
    /// Two values of the same type can be compared using the usual
    /// comparison for values of this type. Two values of distinct
    /// types cannot be compared.
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.get_type() != other.get_type() {
            None
        } else {
            self.0.partial_cmp(&other.0)
        }
    }
}
<commit_msg>ExtNumeric is now fully public<commit_after>//!
//! Values manipulated by endpoints
//!

use std::time::Duration;
use std::cmp::{PartialOrd, Ordering};

extern crate chrono;
use self::chrono::{DateTime, Local};

extern crate serde_json;

///
/// The type of values manipulated by endpoints.
///
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub enum Type {
    ///
    /// # Trivial values
    ///

    /// An empty value. Used for instance to inform that a countdown
    /// has reached 0 or that a device is ready.
    Unit,

    /// A boolean. Used for instance for on-off switches, presence
    /// detectors, etc.
    Bool,

    ///
    /// # Time
    ///

    /// A duration. Used for instance in countdowns.
    Duration,

    /// A precise timestamp. Used for instance to determine when an
    /// event has taken place.
    TimeStamp,

    Temperature,

    ///
    /// ...
    ///
    Color,
    Json,
    Binary,
    ExtNumeric,
}

/// A temperature. Internal representation may be either Fahrenheit or
/// Celcius. The FoxBox adapters are expected to perform conversions
/// to the format requested by their devices.
#[derive(Debug, Clone, PartialEq)]
pub enum Temperature {
    /// Fahrenheit
    F(f64),
    /// Celcius
    C(f64),
}

impl Temperature {
    /// Get a temperature in Fahrenheit.
    pub fn as_f(&self) -> f64 {
        unimplemented!();
    }

    /// Get a temperature in Celcius.
    pub fn as_c(&self) -> f64 {
        unimplemented!();
    }
}

impl PartialOrd for Temperature {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.as_c().partial_cmp(&other.as_c())
    }
}

/// A color. Internal representation may vary. The FoxBox adapters are
/// expected to perform conversions to the format requested by their
/// device.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum Color {
    RGBA(f64, f64, f64, f64, f64)
}

/// Representation of an object in JSON. It is often (albeit not
/// always) possible to choose a more precise data structure for
/// representing values send/accepted by a service. If possible,
/// adapters should rather pick such more precise data structure.
#[derive(Debug, Clone, PartialEq)]
pub struct Json(serde_json::value::Value);

impl PartialOrd for Json {
    /// Two Json objects are never comparable to each other.
    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
        None
    }
}

/// A data structure holding a numeric value of a type that has not
/// been standardized yet.
#[derive(Debug, Clone, PartialEq)]
pub struct ExtNumeric {
    pub value: f64,

    /// The vendor. Used for namespacing purposes, to avoid
    /// confusing two incompatible extensions with similar
    /// names. For instance, "foxlink@mozilla.com".
    pub vendor: String,

    /// Identification of the adapter introducing this value.
    /// Designed to aid with tracing and debugging.
    pub adapter: String,

    /// A string describing the nature of the value, designed to
    /// aid with type-checking.
    ///
    /// Examples: `"GroundHumidity"`.
    pub kind: String,
}

impl PartialOrd for ExtNumeric {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.vendor != other.vendor {
            return None;
        } else if self.kind != other.kind {
            return None;
        } else {
            self.value.partial_cmp(&other.value)
        }
    }
}

/// Base definitions for actual values. Most API clients will rather
/// use `Value`.
///
/// Splitting the defintion between `Value` and `ValueBase` is mostly
/// a convenience to refine the automatically-derived `PartialOrd` on
/// `ValueBase` into something that will never compare two values with
/// different types.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum ValueBase {
    Unit,
    Bool(bool),
    Duration(Duration),
    TimeStamp(chrono::DateTime<Local>),
    Temperature(Temperature),
    Color(Color),

    // FIXME: Add more as we identify needs

    /// A numeric value representing a unit that has not been
    /// standardized yet into the API.
    ExtNumeric(ExtNumeric),
    Json(Json),
    Binary {data: Vec<u8>, mimetype: String}
}

impl ValueBase {
    pub fn get_type(&self) -> Type {
        match *self {
            ValueBase::Unit => Type::Unit,
            ValueBase::Bool(_) => Type::Bool,
            ValueBase::Duration(_) => Type::Duration,
            ValueBase::TimeStamp(_) => Type::TimeStamp,
            ValueBase::Temperature(_) => Type::Temperature,
            ValueBase::Color(_) => Type::Color,
            ValueBase::Json(_) => Type::Json,
            ValueBase::Binary{..} => Type::Binary,
            ValueBase::ExtNumeric(_) => Type::ExtNumeric,
        }
    }
}

/// Representation of an actual value that can be sent to/received
/// from a service.
#[derive(Debug, Clone, PartialEq)]
pub struct Value(ValueBase);

impl Value {
    /// Get the type attached to a value.
    pub fn get_type(&self) -> Type {
        self.0.get_type()
    }
}

impl PartialOrd for Value {
    /// Two values of the same type can be compared using the usual
    /// comparison for values of this type. Two values of distinct
    /// types cannot be compared.
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.get_type() != other.get_type() {
            None
        } else {
            self.0.partial_cmp(&other.0)
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::{
  Add, AddAssign,
  Sub, SubAssign,
  Mul, MulAssign,
  Div, DivAssign,
  Index, IndexMut,
};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
  pub fn dot(&self, other: Vec3) -> f64 {
    self.i * other.i + self.j * other.j + self.k * other.k
  }
  pub fn cross(&self, other: Vec3) -> Vec3 {
    return Vec3 {
      i: self.j * other.k - self.k * other.j,
      j: -(self.i * other.k - self.k * other.i),
      k: self.i * other.j - self.j * other.i,
    };
  }
  pub fn unit_vector(&self) -> Vec3 {
    return *self / self.length()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul<Vec3> for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl Mul<f64> for Vec3 {
  type Output = Vec3;
  fn mul(self, scalar: f64) -> Vec3 {
    Vec3 {i: self.i * scalar, j: self.j * scalar, k: self.k * scalar}
  }
}

impl MulAssign<Vec3> for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}

impl MulAssign<f64> for Vec3 {
  fn mul_assign(&mut self, scalar: f64) {
    *self = Vec3 {
      i: self.i * scalar,
      j: self.j * scalar,
      k: self.k * scalar,
    }
  }
}

impl Div<Vec3> for Vec3 {
  type Output = Vec3;
  fn div(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i / rhs.i, j: self.j / rhs.j, k: self.k / rhs.k}
  }
}

impl Div<f64> for Vec3 {
  type Output = Vec3;
  fn div(self, scalar: f64) -> Vec3 {
    Vec3 {i: self.i / scalar, j: self.j / scalar, k: self.k / scalar}
  }
}

impl DivAssign<Vec3> for Vec3 {
  fn div_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i / rhs.i,
      j: self.j / rhs.j,
      k: self.k / rhs.k,
    }
  }
}

impl DivAssign<f64> for Vec3 {
  fn div_assign(&mut self, scalar: f64) {
    *self = Vec3 {
      i: self.i / scalar,
      j: self.j / scalar,
      k: self.k / scalar,
    }
  }
}

impl Index<i32> for Vec3 {
  type Output = f64;
  fn index(&self, idx: i32) -> &f64 {
    match idx {
      0 => &self.i,
      1 => &self.j,
      2 => &self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

impl IndexMut<i32> for Vec3 {
  fn index_mut<'a>(&'a mut self, idx: i32) -> &'a mut f64 {
    match idx {
      0 => &mut self.i,
      1 => &mut self.j,
      2 => &mut self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

#[cfg(test)]
mod should {
  use super::Vec3;
  #[test]
  fn add() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let sum = v1 + v2;
    assert_eq!(sum.i, 3.0);
    assert_eq!(sum.j, 3.0);
    assert_eq!(sum.k, 3.0);
  }
  #[test]
  fn add_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 += v2;
    assert_eq!(v1.i, 3.0);
    assert_eq!(v1.j, 3.0);
    assert_eq!(v1.k, 3.0);
  }
  #[test]
  fn subtract() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let diff = v1 - v2;
    assert_eq!(diff.i, -1.0);
    assert_eq!(diff.j, -1.0);
    assert_eq!(diff.k, -1.0);
  }
  #[test]
  fn subtract_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 -= v2;
    assert_eq!(v1.i, -1.0);
    assert_eq!(v1.j, -1.0);
    assert_eq!(v1.k, -1.0);
  }
  #[test]
  fn multiply_by_vec3_elementwise() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let product = v1 * v2;
    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_by_vec3_assign_elementwise() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 *= v2;
    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
  #[test]
  fn multiply_by_f64() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let product = v1 * 3.0;

    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_by_f64_assign() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 *= 3.0;

    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
  #[test]
  fn divide_by_vec3_elementwise() {
    let v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let quotient = v1 / v2;
    assert_eq!(quotient.i, 2.0);
    assert_eq!(quotient.j, 2.0);
    assert_eq!(quotient.k, 2.0);
  }
  #[test]
  fn divide_by_vec3_assign_elementwise() {
    let mut v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 /= v2;
    assert_eq!(v1.i, 2.0);
    assert_eq!(v1.j, 2.0);
    assert_eq!(v1.k, 2.0);
  }
  #[test]
  fn divide_by_f64() {
    let v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let quotient = v1 / 3.0;

    assert_eq!(quotient.i, 2.0);
    assert_eq!(quotient.j, 2.0);
    assert_eq!(quotient.k, 2.0);
  }
  #[test]
  fn divide_by_f64_assign() {
    let mut v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    v1 /= 3.0;

    assert_eq!(v1.i, 2.0);
    assert_eq!(v1.j, 2.0);
    assert_eq!(v1.k, 2.0);
  }
  #[test]
  fn allow_index_access() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[0], 2.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
  #[test]
  #[should_panic(expected = "index out of range: 9")]
  fn panic_on_bad_index() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[9], 2.0);
  }
  #[test]
  fn allow_index_mut_access() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1[0] = 9.0;

    assert_eq!(v1[0], 9.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }

  #[test]
  fn calculate_length() {
    let v1 = Vec3 { i: 4.0, j: 4.0, k: 2.0};

    assert_eq!(v1.length(), 6.0);
  }
  #[test]
  fn calculate_length_with_some_zeros() {
    let v2 = Vec3 { i: 4.0, j: 0.0, k: 0.0};

    assert_eq!(v2.length(), 4.0);
  }
  #[test]
  fn calculate_length_for_zero_vector() {
    let v2 = Vec3 { i: 0.0, j: 0.0, k: 0.0};

    assert_eq!(v2.length(), 0.0);
  }
  #[test]
  fn calculate_dot_product() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};

    let product = v1.dot(v2);

    assert_eq!(product, 18.0);
  }
  #[test]
  fn calculate_cross_product() {
    let v1 = Vec3 { i: 1.0, j: 0.0, k: 0.0};
    let v2 = Vec3 { i: 0.0, j: 1.0, k: 0.0};

    let product = v1.cross(v2);

    assert_eq!(product[0], 0.0);
    assert_eq!(product[1], 0.0);
    assert_eq!(product[2], 1.0);
  }
  #[test]
  fn calculate_unit_vector_simple() {
    let v1 = Vec3 { i: 4.0, j: 0.0, k: 0.0};

    let product = v1.unit_vector();

    assert_eq!(product[0], 1.0);
    assert_eq!(product[1], 0.0);
    assert_eq!(product[2], 0.0);
  }
  #[test]
  fn calculate_unit_vector_multple() {
    let v1 = Vec3 { i: 4.0, j: 4.0, k: 2.0};

    let product = v1.unit_vector();

    assert_eq!(product[0], 4.0 / 6.0);
    assert_eq!(product[1], 4.0 / 6.0);
    assert_eq!(product[2], 2.0 / 6.0);
  }
}<commit_msg>Add functions for coordinate and color components access<commit_after>use std::ops::{
  Add, AddAssign,
  Sub, SubAssign,
  Mul, MulAssign,
  Div, DivAssign,
  Index, IndexMut,
};

#[derive(Debug, Copy, Clone)]
pub struct Vec3 {
  pub i : f64,
  pub j : f64,
  pub k : f64,
}

impl Vec3 {
  pub fn x(&self) -> f64 { self.i }
  pub fn y(&self) -> f64 { self.j }
  pub fn z(&self) -> f64 { self.k }
  pub fn r(&self) -> f64 { self.i }
  pub fn g(&self) -> f64 { self.j }
  pub fn b(&self) -> f64 { self.k }
  pub fn length(&self) -> f64 {
    (self.i * self.i + self.j * self.j + self.k * self.k).sqrt()
  }
  pub fn dot(&self, other: Vec3) -> f64 {
    self.i * other.i + self.j * other.j + self.k * other.k
  }
  pub fn cross(&self, other: Vec3) -> Vec3 {
    return Vec3 {
      i: self.j * other.k - self.k * other.j,
      j: -(self.i * other.k - self.k * other.i),
      k: self.i * other.j - self.j * other.i,
    };
  }
  pub fn unit_vector(&self) -> Vec3 {
    return *self / self.length()
  }
}

impl Add for Vec3 {
  type Output = Vec3;
  fn add(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i + other.i, j: self.j + other.j, k: self.k + other.k}
  }
}

impl AddAssign for Vec3 {
  fn add_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i + other.i,
      j: self.j + other.j,
      k: self.k + other.k,
    };
  }
}

impl Sub for Vec3 {
  type Output = Vec3;
  fn sub(self, other: Vec3) -> Vec3 {
      Vec3 {i: self.i - other.i, j: self.j - other.j, k: self.k - other.k}
  }
}

impl SubAssign for Vec3 {
  fn sub_assign(&mut self, other: Vec3) {
    *self = Vec3 {
      i: self.i - other.i,
      j: self.j - other.j,
      k: self.k - other.k,
    }
  }
}

impl Mul<Vec3> for Vec3 {
  type Output = Vec3;
  fn mul(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i * rhs.i, j: self.j * rhs.j, k: self.k * rhs.k}
  }
}

impl Mul<f64> for Vec3 {
  type Output = Vec3;
  fn mul(self, scalar: f64) -> Vec3 {
    Vec3 {i: self.i * scalar, j: self.j * scalar, k: self.k * scalar}
  }
}

impl MulAssign<Vec3> for Vec3 {
  fn mul_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i * rhs.i,
      j: self.j * rhs.j,
      k: self.k * rhs.k,
    }
  }
}

impl MulAssign<f64> for Vec3 {
  fn mul_assign(&mut self, scalar: f64) {
    *self = Vec3 {
      i: self.i * scalar,
      j: self.j * scalar,
      k: self.k * scalar,
    }
  }
}

impl Div<Vec3> for Vec3 {
  type Output = Vec3;
  fn div(self, rhs: Vec3) -> Vec3 {
    Vec3 {i: self.i / rhs.i, j: self.j / rhs.j, k: self.k / rhs.k}
  }
}

impl Div<f64> for Vec3 {
  type Output = Vec3;
  fn div(self, scalar: f64) -> Vec3 {
    Vec3 {i: self.i / scalar, j: self.j / scalar, k: self.k / scalar}
  }
}

impl DivAssign<Vec3> for Vec3 {
  fn div_assign(&mut self, rhs: Vec3) {
    *self = Vec3 {
      i: self.i / rhs.i,
      j: self.j / rhs.j,
      k: self.k / rhs.k,
    }
  }
}

impl DivAssign<f64> for Vec3 {
  fn div_assign(&mut self, scalar: f64) {
    *self = Vec3 {
      i: self.i / scalar,
      j: self.j / scalar,
      k: self.k / scalar,
    }
  }
}

impl Index<i32> for Vec3 {
  type Output = f64;
  fn index(&self, idx: i32) -> &f64 {
    match idx {
      0 => &self.i,
      1 => &self.j,
      2 => &self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

impl IndexMut<i32> for Vec3 {
  fn index_mut<'a>(&'a mut self, idx: i32) -> &'a mut f64 {
    match idx {
      0 => &mut self.i,
      1 => &mut self.j,
      2 => &mut self.k,
      _ => panic!("index out of range: {}", idx),
    }
  }
}

#[cfg(test)]
mod should {
  use super::Vec3;
  #[test]
  fn add() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let sum = v1 + v2;
    assert_eq!(sum.i, 3.0);
    assert_eq!(sum.j, 3.0);
    assert_eq!(sum.k, 3.0);
  }
  #[test]
  fn add_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 += v2;
    assert_eq!(v1.i, 3.0);
    assert_eq!(v1.j, 3.0);
    assert_eq!(v1.k, 3.0);
  }
  #[test]
  fn subtract() {
    let v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let diff = v1 - v2;
    assert_eq!(diff.i, -1.0);
    assert_eq!(diff.j, -1.0);
    assert_eq!(diff.k, -1.0);
  }
  #[test]
  fn subtract_assign() {
    let mut v1 = Vec3 { i: 1.0, j: 1.0, k: 1.0};
    let v2 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 -= v2;
    assert_eq!(v1.i, -1.0);
    assert_eq!(v1.j, -1.0);
    assert_eq!(v1.k, -1.0);
  }
  #[test]
  fn multiply_by_vec3_elementwise() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let product = v1 * v2;
    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_by_vec3_assign_elementwise() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 *= v2;
    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
  #[test]
  fn multiply_by_f64() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let product = v1 * 3.0;

    assert_eq!(product.i, 6.0);
    assert_eq!(product.j, 6.0);
    assert_eq!(product.k, 6.0);
  }
  #[test]
  fn multiply_by_f64_assign() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1 *= 3.0;

    assert_eq!(v1.i, 6.0);
    assert_eq!(v1.j, 6.0);
    assert_eq!(v1.k, 6.0);
  }
  #[test]
  fn divide_by_vec3_elementwise() {
    let v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    let quotient = v1 / v2;
    assert_eq!(quotient.i, 2.0);
    assert_eq!(quotient.j, 2.0);
    assert_eq!(quotient.k, 2.0);
  }
  #[test]
  fn divide_by_vec3_assign_elementwise() {
    let mut v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};
    v1 /= v2;
    assert_eq!(v1.i, 2.0);
    assert_eq!(v1.j, 2.0);
    assert_eq!(v1.k, 2.0);
  }
  #[test]
  fn divide_by_f64() {
    let v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    let quotient = v1 / 3.0;

    assert_eq!(quotient.i, 2.0);
    assert_eq!(quotient.j, 2.0);
    assert_eq!(quotient.k, 2.0);
  }
  #[test]
  fn divide_by_f64_assign() {
    let mut v1 = Vec3 { i: 6.0, j: 6.0, k: 6.0};
    v1 /= 3.0;

    assert_eq!(v1.i, 2.0);
    assert_eq!(v1.j, 2.0);
    assert_eq!(v1.k, 2.0);
  }
  #[test]
  fn allow_index_access() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[0], 2.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }
  #[test]
  #[should_panic(expected = "index out of range: 9")]
  fn panic_on_bad_index() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};

    assert_eq!(v1[9], 2.0);
  }
  #[test]
  fn allow_index_mut_access() {
    let mut v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    v1[0] = 9.0;

    assert_eq!(v1[0], 9.0);
    assert_eq!(v1[1], 2.0);
    assert_eq!(v1[2], 2.0);
  }

  #[test]
  fn calculate_length() {
    let v1 = Vec3 { i: 4.0, j: 4.0, k: 2.0};

    assert_eq!(v1.length(), 6.0);
  }
  #[test]
  fn calculate_length_with_some_zeros() {
    let v2 = Vec3 { i: 4.0, j: 0.0, k: 0.0};

    assert_eq!(v2.length(), 4.0);
  }
  #[test]
  fn calculate_length_for_zero_vector() {
    let v2 = Vec3 { i: 0.0, j: 0.0, k: 0.0};

    assert_eq!(v2.length(), 0.0);
  }
  #[test]
  fn calculate_dot_product() {
    let v1 = Vec3 { i: 2.0, j: 2.0, k: 2.0};
    let v2 = Vec3 { i: 3.0, j: 3.0, k: 3.0};

    let product = v1.dot(v2);

    assert_eq!(product, 18.0);
  }
  #[test]
  fn calculate_cross_product() {
    let v1 = Vec3 { i: 1.0, j: 0.0, k: 0.0};
    let v2 = Vec3 { i: 0.0, j: 1.0, k: 0.0};

    let product = v1.cross(v2);

    assert_eq!(product[0], 0.0);
    assert_eq!(product[1], 0.0);
    assert_eq!(product[2], 1.0);
  }
  #[test]
  fn calculate_unit_vector_simple() {
    let v1 = Vec3 { i: 4.0, j: 0.0, k: 0.0};

    let product = v1.unit_vector();

    assert_eq!(product[0], 1.0);
    assert_eq!(product[1], 0.0);
    assert_eq!(product[2], 0.0);
  }
  #[test]
  fn calculate_unit_vector_multple() {
    let v1 = Vec3 { i: 4.0, j: 4.0, k: 2.0};

    let product = v1.unit_vector();

    assert_eq!(product[0], 4.0 / 6.0);
    assert_eq!(product[1], 4.0 / 6.0);
    assert_eq!(product[2], 2.0 / 6.0);
  }
  #[test]
  fn have_color_access_functions() {
    let v1 = Vec3 { i: 1.0, j: 2.0, k: 3.0};

    assert_eq!(v1.r(), 1.0);
    assert_eq!(v1.g(), 2.0);
    assert_eq!(v1.b(), 3.0);
  }
  #[test]
  fn have_coordinate_access_functions() {
    let v1 = Vec3 { i: 1.0, j: 2.0, k: 3.0};

    assert_eq!(v1.x(), 1.0);
    assert_eq!(v1.y(), 2.0);
    assert_eq!(v1.z(), 3.0);
  }
}<|endoftext|>


<commit_before>use std::ops::{Deref, DerefMut};
use std::mem;
use std::collections::HashMap;
use property::Property;

use std::rc::Rc;
use edge::{RawEdge,Edge};
use graph::TraversableToVertex;
use std::sync::RwLock;

/*
* storing in & out edges seperately should cut down on the number of "things" i have to traverse
* if a vertex has 10k edges (5k in and out 5k out) then doing something like*   g(v).outV()
* should be ok
*/
#[derive(Debug, Clone)]
pub struct RawVertex {
    pub id: i64,
    pub properties: HashMap<String, Property>,
    // pointers on both sides, yay
    pub out_edges: Vec<Edge>,
    pub in_edges:  Vec<Edge>,
}

impl RawVertex {
    pub fn new(id: i64) -> Rc<Box<RwLock<RawVertex>>> {
        let mut props  = HashMap::new();

        let vertex = RawVertex{id:id,
                        properties: props,
                        out_edges: Vec::new(),
                        in_edges: Vec::new()};

        Rc::new(Box::new(RwLock::new(vertex)))
    }
}

#[derive(Clone, Debug)]
pub struct Vertex {
    pub id: i64,
    pub v: Rc<Box<RwLock<RawVertex>>>,
}

impl Vertex {

	pub fn new(id: i64) -> Vertex {
        let raw = RawVertex::new(id);
        Vertex{id:id, v:raw}
	}

    pub fn add_edge(&mut self, to_vertex: &mut Vertex, label: &str) -> Edge {
        println!("add_edge() with label {}", label);

        // let in_vertex =  &mut *(self.v);
        // let out_vertex = &mut *(to_vertex.v);

        // why do i need the raw shit?
        // let mut in_vertex = self;
        // let mut out_vertex = to_vertex;
        // create the edge
        println!("adding vertex of edge {}", label.to_string());

        // keep it on the heap but manage it myself
        let edge = Edge::new(self.clone(),
                             to_vertex.clone(),
                             label.to_string());

        self.write().unwrap().out_edges.push(edge.clone());
        // self.out_edges.push(edge.clone());

        to_vertex.write().unwrap().in_edges.push(edge.clone());
        edge
    }

    // TODO switch to accepting a &str
    pub fn set_property(&mut self, field: &str, value: Property) {
        self.write().unwrap().properties.insert(field.to_string(), value);
    }

    pub fn get_property(&self, field:&str) -> Option<&Property> {
        self.write().unwrap().properties.get(&field.to_string())
    }

	pub fn outE(&self) -> Vec<Edge> {
		let mut result = Vec::new();
		for edge in self.read().unwrap().out_edges.iter() {
			result.push(edge.clone());
		}
		result
	}

	pub fn inE(&self) -> Vec<Edge> {
		let mut result = Vec::new();
		for edge in self.read().unwrap().in_edges.iter() {
			result.push(edge.clone());
		}
		result
	}

}

impl TraversableToVertex for Vertex {
	/* basic traversal operations
	   cannot be chained
	   look at traversal.rs for breadth first chaining
	*/

	/* returns all the outV vertex proxies
	   mainly for internal use
	*/
	fn outV(&self, labels: &[&str]) -> Vec<Vertex> {
		let mut result = Vec::new();

        // convert our labels to a vector of strings
        let mut labels_as_strings : Vec<String> = Vec::new();

        for l in labels {
            let s = l.to_string();
            labels_as_strings.push(l.to_string());
        }

		for edge in self.out_edges.iter() {
            if labels.is_empty() || labels_as_strings.contains(&edge.label) {
				result.push(edge.to_vertex.clone());
            }
		}
		result
	}
	fn inV(&self) -> Vec<Vertex> {
		let mut result = Vec::new();
		for edge in self.in_edges.iter() {
			result.push(edge.from_vertex.clone());
		}
		result
	}

}

impl Deref for Vertex {
    type Target = Rc<Box<RwLock<RawVertex>>>;

    fn deref<'a>(&'a self) -> &'a Rc<Box<RwLock<RawVertex>>> {
        &self.v
    }
}

impl DerefMut for Vertex {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Rc<Box<RwLock<RawVertex>>> {
        &mut self.v
    }
}
<commit_msg>defeated a round of errors only to be slammed by new ones<commit_after>use std::ops::{Deref, DerefMut};
use std::mem;
use std::collections::HashMap;
use property::Property;

use std::rc::Rc;
use edge::{RawEdge,Edge};
use graph::TraversableToVertex;
use std::sync::RwLock;

/*
* storing in & out edges seperately should cut down on the number of "things" i have to traverse
* if a vertex has 10k edges (5k in and out 5k out) then doing something like*   g(v).outV()
* should be ok
*/
#[derive(Debug, Clone)]
pub struct RawVertex {
    pub id: i64,
    pub properties: HashMap<String, Property>,
    // pointers on both sides, yay
    pub out_edges: Vec<Edge>,
    pub in_edges:  Vec<Edge>,
}

impl RawVertex {
    pub fn new(id: i64) -> Rc<Box<RwLock<RawVertex>>> {
        let mut props  = HashMap::new();

        let vertex = RawVertex{id:id,
                        properties: props,
                        out_edges: Vec::new(),
                        in_edges: Vec::new()};

        Rc::new(Box::new(RwLock::new(vertex)))
    }
}

#[derive(Clone, Debug)]
pub struct Vertex {
    pub id: i64,
    pub v: Rc<Box<RwLock<RawVertex>>>,
}

impl Vertex {

	pub fn new(id: i64) -> Vertex {
        let raw = RawVertex::new(id);
        Vertex{id:id, v:raw}
	}

    pub fn add_edge(&mut self, to_vertex: &mut Vertex, label: &str) -> Edge {
        println!("add_edge() with label {}", label);

        // let in_vertex =  &mut *(self.v);
        // let out_vertex = &mut *(to_vertex.v);

        // why do i need the raw shit?
        // let mut in_vertex = self;
        // let mut out_vertex = to_vertex;
        // create the edge
        println!("adding vertex of edge {}", label.to_string());

        // keep it on the heap but manage it myself
        let edge = Edge::new(self.clone(),
                             to_vertex.clone(),
                             label.to_string());

        self.write().unwrap().out_edges.push(edge.clone());
        // self.out_edges.push(edge.clone());

        to_vertex.write().unwrap().in_edges.push(edge.clone());
        edge
    }

    // TODO switch to accepting a &str
    pub fn set_property(&mut self, field: &str, value: Property) {
        self.write().unwrap().properties.insert(field.to_string(), value);
    }

    pub fn get_property(&self, field:&str) -> Option<Property> {
        self.write().unwrap().properties.get(&field.to_string()).cloned()
    }

	pub fn outE(&self) -> Vec<Edge> {
		let mut result = Vec::new();
		for edge in self.read().unwrap().out_edges.iter() {
			result.push(edge.clone());
		}
		result
	}

	pub fn inE(&self) -> Vec<Edge> {
		let mut result = Vec::new();
		for edge in self.read().unwrap().in_edges.iter() {
			result.push(edge.clone());
		}
		result
	}

}

impl TraversableToVertex for Vertex {
	/* basic traversal operations
	   cannot be chained
	   look at traversal.rs for breadth first chaining
	*/

	/* returns all the outV vertex proxies
	   mainly for internal use
	*/
	fn outV(&self, labels: &[&str]) -> Vec<Vertex> {
		let mut result = Vec::new();

        // convert our labels to a vector of strings
        let mut labels_as_strings : Vec<String> = Vec::new();

        for l in labels {
            let s = l.to_string();
            labels_as_strings.push(l.to_string());
        }

		for edge in self.read().unwrap().out_edges.iter() {
            if labels.is_empty() || labels_as_strings.contains(&edge.label) {
				result.push(edge.to_vertex.clone());
            }
		}
		result
	}
	fn inV(&self) -> Vec<Vertex> {
		let mut result = Vec::new();
		for edge in self.read().unwrap().in_edges.iter() {
			result.push(edge.from_vertex.clone());
		}
		result
	}

}

impl Deref for Vertex {
    type Target = Rc<Box<RwLock<RawVertex>>>;

    fn deref<'a>(&'a self) -> &'a Rc<Box<RwLock<RawVertex>>> {
        &self.v
    }
}

impl DerefMut for Vertex {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Rc<Box<RwLock<RawVertex>>> {
        &mut self.v
    }
}
<|endoftext|>