<commit_before>use std::marker::PhantomData;
use std::io::Read;
use std::sync::Mutex;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;
use std::net::SocketAddr;

use hyper::header::ContentType;
use hyper::method::Method;
use hyper::server::{Server, Handler, Request, Response};
use hyper::uri::RequestUri::AbsolutePath;
use hyper::status::StatusCode;

use command::{WebDriverMessage, WebDriverCommand};
use error::{WebDriverResult, WebDriverError, ErrorStatus};
use httpapi::{WebDriverHttpApi, WebDriverExtensionRoute, VoidWebDriverExtensionRoute};
use response::WebDriverResponse;

enum DispatchMessage<U: WebDriverExtensionRoute> {
    HandleWebDriver(WebDriverMessage<U>, Sender<WebDriverResult<WebDriverResponse>>),
    Quit
}

#[derive(PartialEq, Clone)]
pub struct Session {
    id: String
}

impl Session {
    fn new(id: String) -> Session {
        Session {
            id: id
        }
    }
}

pub trait WebDriverHandler<U: WebDriverExtensionRoute=VoidWebDriverExtensionRoute> : Send {
    fn handle_command(&mut self, session: &Option<Session>, msg: &WebDriverMessage<U>) -> WebDriverResult<WebDriverResponse>;
    fn delete_session(&mut self, session: &Option<Session>);
}

struct Dispatcher<T: WebDriverHandler<U>,
                  U: WebDriverExtensionRoute> {
    handler: T,
    session: Option<Session>,
    extension_type: PhantomData<U>,
}

impl <T: WebDriverHandler<U>,
      U: WebDriverExtensionRoute> Dispatcher<T,U> {
    fn new(handler: T) -> Dispatcher<T,U> {
        Dispatcher {
            handler: handler,
            session: None,
            extension_type: PhantomData
        }
    }

    fn run(&mut self, msg_chan: Receiver<DispatchMessage<U>>) {
        loop {
            match msg_chan.recv() {
                Ok(DispatchMessage::HandleWebDriver(msg, resp_chan)) => {
                    let resp = match self.check_session(&msg) {
                        Ok(_) => self.handler.handle_command(&self.session, &msg),
                        Err(e) => Err(e)
                    };

                    match resp {
                        Ok(WebDriverResponse::NewSession(ref new_session)) => {
                            self.session = Some(Session::new(new_session.sessionId.clone()));
                        },
                        Ok(WebDriverResponse::DeleteSession) => {
                            self.delete_session();
                        },
                        Err(ref x) if x.delete_session() => {
                            self.delete_session();
                        }
                        _ => {}
                    }

                    if resp_chan.send(resp).is_err() {
                        error!("Sending response to the main thread failed");
                    };
                },
                Ok(DispatchMessage::Quit) => {
                    break;
                },
                Err(_) => panic!("Error receiving message in handler")
            }
        }
    }

    fn delete_session(&mut self) {
        debug!("Deleting session");
        self.handler.delete_session(&self.session);
        self.session = None;
    }

    fn check_session(&self, msg: &WebDriverMessage<U>) -> WebDriverResult<()> {
        match msg.session_id {
            Some(ref msg_session_id) => {
                match self.session {
                    Some(ref existing_session) => {
                        if existing_session.id != *msg_session_id {
                            Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                format!("Got unexpected session id {} expected {}",
                                        msg_session_id,
                                        existing_session.id)))
                        } else {
                            Ok(())
                        }
                    },
                    None => Ok(())
                }
            },
            None => {
                match self.session {
                    Some(_) => {
                        match msg.command {
                            WebDriverCommand::NewSession(_) => {
                                Err(WebDriverError::new(
                                    ErrorStatus::UnsupportedOperation,
                                    "Session is already started"))
                            },
                            _ => {
                                //This should be impossible
                                error!("Got a message with no session id");
                                Err(WebDriverError::new(
                                    ErrorStatus::UnknownError,
                                    "Got a command with no session?!"))
                            }
                        }
                    },
                    None => {
                        match msg.command {
                            WebDriverCommand::NewSession(_) => Ok(()),

                            _ => Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                "Tried to run a command before creating a session"))
                        }
                    }
                }
            }
        }
    }
}

struct HttpHandler<U: WebDriverExtensionRoute> {
    chan: Mutex<Sender<DispatchMessage<U>>>,
    api: Mutex<WebDriverHttpApi<U>>
}

impl <U: WebDriverExtensionRoute> HttpHandler<U> {
    fn new(api: WebDriverHttpApi<U>, chan: Sender<DispatchMessage<U>>) -> HttpHandler<U> {
        HttpHandler {
            chan: Mutex::new(chan),
            api: Mutex::new(api)
        }
    }
}

impl <U: WebDriverExtensionRoute> Handler for HttpHandler<U> {
    fn handle(&self, req: Request, res: Response) {
        let mut req = req;
        let mut res = res;

        let mut body = String::new();
        if let Method::Post = req.method {
            req.read_to_string(&mut body).unwrap();
        }
        debug!("Got request {} {:?}", req.method, req.uri);
        match req.uri {
            AbsolutePath(path) => {
                let msg_result = {
                    // The fact that this locks for basically the whole request doesn't
                    // matter as long as we are only handling one request at a time.
                    match self.api.lock() {
                        Ok(ref api) => {
                            api.decode_request(req.method, &path[..], &body[..])
                        },
                        Err(_) => return
                    }
                };
                let (status, resp_body) = match msg_result {
                    Ok(message) => {
                        let (send_res, recv_res) = channel();
                        match self.chan.lock() {
                            Ok(ref c) => {
                                let res = c.send(DispatchMessage::HandleWebDriver(message,
                                                                                send_res));
                                match res {
                                    Ok(x) => x,
                                    Err(_) => {
                                        error!("Something terrible happened");
                                        return
                                    }
                                }
                            },
                            Err(_) => {
                                error!("Something terrible happened");
                                return
                            }
                        }
                        match recv_res.recv() {
                            Ok(data) => match data {
                                Ok(response) => (StatusCode::Ok, response.to_json_string()),
                                Err(err) => (err.http_status(), err.to_json_string()),
                            },
                            Err(e) => panic!("Error reading response: {:?}", e)
                        }
                    },
                    Err(err) => {
                        (err.http_status(), err.to_json_string())
                    }
                };
                debug!("Returning status {:?}", status);
                debug!("Returning body {}", resp_body);
                {
                    let resp_status = res.status_mut();
                    *resp_status = status;
                }
                res.headers_mut().set(ContentType::json());
                res.send(&resp_body.as_bytes()).unwrap();
            },
            _ => {}
        }
    }
}

pub fn start<T: 'static+WebDriverHandler<U>,
             U: 'static+WebDriverExtensionRoute>(address: SocketAddr,
                                                 handler: T,
                                                 extension_routes:Vec<(Method, &str, U)>) {
    let (msg_send, msg_recv) = channel();

    let api = WebDriverHttpApi::new(extension_routes);
    let http_handler = HttpHandler::new(api, msg_send);
    let mut server = Server::http(address).unwrap();
    server.keep_alive(None);

    let builder = thread::Builder::new().name("webdriver dispatcher".to_string());
    builder.spawn(move || {
        let mut dispatcher = Dispatcher::new(handler);
        dispatcher.run(msg_recv)
    }).unwrap();
    server.handle(http_handler).unwrap();
}
<commit_msg>Pass ownership of WebDriverMessage to handle_command.<commit_after>use std::marker::PhantomData;
use std::io::Read;
use std::sync::Mutex;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;
use std::net::SocketAddr;

use hyper::header::ContentType;
use hyper::method::Method;
use hyper::server::{Server, Handler, Request, Response};
use hyper::uri::RequestUri::AbsolutePath;
use hyper::status::StatusCode;

use command::{WebDriverMessage, WebDriverCommand};
use error::{WebDriverResult, WebDriverError, ErrorStatus};
use httpapi::{WebDriverHttpApi, WebDriverExtensionRoute, VoidWebDriverExtensionRoute};
use response::WebDriverResponse;

enum DispatchMessage<U: WebDriverExtensionRoute> {
    HandleWebDriver(WebDriverMessage<U>, Sender<WebDriverResult<WebDriverResponse>>),
    Quit
}

#[derive(PartialEq, Clone)]
pub struct Session {
    id: String
}

impl Session {
    fn new(id: String) -> Session {
        Session {
            id: id
        }
    }
}

pub trait WebDriverHandler<U: WebDriverExtensionRoute=VoidWebDriverExtensionRoute> : Send {
    fn handle_command(&mut self, session: &Option<Session>, msg: WebDriverMessage<U>) -> WebDriverResult<WebDriverResponse>;
    fn delete_session(&mut self, session: &Option<Session>);
}

struct Dispatcher<T: WebDriverHandler<U>,
                  U: WebDriverExtensionRoute> {
    handler: T,
    session: Option<Session>,
    extension_type: PhantomData<U>,
}

impl <T: WebDriverHandler<U>,
      U: WebDriverExtensionRoute> Dispatcher<T,U> {
    fn new(handler: T) -> Dispatcher<T,U> {
        Dispatcher {
            handler: handler,
            session: None,
            extension_type: PhantomData
        }
    }

    fn run(&mut self, msg_chan: Receiver<DispatchMessage<U>>) {
        loop {
            match msg_chan.recv() {
                Ok(DispatchMessage::HandleWebDriver(msg, resp_chan)) => {
                    let resp = match self.check_session(&msg) {
                        Ok(_) => self.handler.handle_command(&self.session, msg),
                        Err(e) => Err(e)
                    };

                    match resp {
                        Ok(WebDriverResponse::NewSession(ref new_session)) => {
                            self.session = Some(Session::new(new_session.sessionId.clone()));
                        },
                        Ok(WebDriverResponse::DeleteSession) => {
                            self.delete_session();
                        },
                        Err(ref x) if x.delete_session() => {
                            self.delete_session();
                        }
                        _ => {}
                    }

                    if resp_chan.send(resp).is_err() {
                        error!("Sending response to the main thread failed");
                    };
                },
                Ok(DispatchMessage::Quit) => {
                    break;
                },
                Err(_) => panic!("Error receiving message in handler")
            }
        }
    }

    fn delete_session(&mut self) {
        debug!("Deleting session");
        self.handler.delete_session(&self.session);
        self.session = None;
    }

    fn check_session(&self, msg: &WebDriverMessage<U>) -> WebDriverResult<()> {
        match msg.session_id {
            Some(ref msg_session_id) => {
                match self.session {
                    Some(ref existing_session) => {
                        if existing_session.id != *msg_session_id {
                            Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                format!("Got unexpected session id {} expected {}",
                                        msg_session_id,
                                        existing_session.id)))
                        } else {
                            Ok(())
                        }
                    },
                    None => Ok(())
                }
            },
            None => {
                match self.session {
                    Some(_) => {
                        match msg.command {
                            WebDriverCommand::NewSession(_) => {
                                Err(WebDriverError::new(
                                    ErrorStatus::UnsupportedOperation,
                                    "Session is already started"))
                            },
                            _ => {
                                //This should be impossible
                                error!("Got a message with no session id");
                                Err(WebDriverError::new(
                                    ErrorStatus::UnknownError,
                                    "Got a command with no session?!"))
                            }
                        }
                    },
                    None => {
                        match msg.command {
                            WebDriverCommand::NewSession(_) => Ok(()),

                            _ => Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                "Tried to run a command before creating a session"))
                        }
                    }
                }
            }
        }
    }
}

struct HttpHandler<U: WebDriverExtensionRoute> {
    chan: Mutex<Sender<DispatchMessage<U>>>,
    api: Mutex<WebDriverHttpApi<U>>
}

impl <U: WebDriverExtensionRoute> HttpHandler<U> {
    fn new(api: WebDriverHttpApi<U>, chan: Sender<DispatchMessage<U>>) -> HttpHandler<U> {
        HttpHandler {
            chan: Mutex::new(chan),
            api: Mutex::new(api)
        }
    }
}

impl <U: WebDriverExtensionRoute> Handler for HttpHandler<U> {
    fn handle(&self, req: Request, res: Response) {
        let mut req = req;
        let mut res = res;

        let mut body = String::new();
        if let Method::Post = req.method {
            req.read_to_string(&mut body).unwrap();
        }
        debug!("Got request {} {:?}", req.method, req.uri);
        match req.uri {
            AbsolutePath(path) => {
                let msg_result = {
                    // The fact that this locks for basically the whole request doesn't
                    // matter as long as we are only handling one request at a time.
                    match self.api.lock() {
                        Ok(ref api) => {
                            api.decode_request(req.method, &path[..], &body[..])
                        },
                        Err(_) => return
                    }
                };
                let (status, resp_body) = match msg_result {
                    Ok(message) => {
                        let (send_res, recv_res) = channel();
                        match self.chan.lock() {
                            Ok(ref c) => {
                                let res = c.send(DispatchMessage::HandleWebDriver(message,
                                                                                send_res));
                                match res {
                                    Ok(x) => x,
                                    Err(_) => {
                                        error!("Something terrible happened");
                                        return
                                    }
                                }
                            },
                            Err(_) => {
                                error!("Something terrible happened");
                                return
                            }
                        }
                        match recv_res.recv() {
                            Ok(data) => match data {
                                Ok(response) => (StatusCode::Ok, response.to_json_string()),
                                Err(err) => (err.http_status(), err.to_json_string()),
                            },
                            Err(e) => panic!("Error reading response: {:?}", e)
                        }
                    },
                    Err(err) => {
                        (err.http_status(), err.to_json_string())
                    }
                };
                debug!("Returning status {:?}", status);
                debug!("Returning body {}", resp_body);
                {
                    let resp_status = res.status_mut();
                    *resp_status = status;
                }
                res.headers_mut().set(ContentType::json());
                res.send(&resp_body.as_bytes()).unwrap();
            },
            _ => {}
        }
    }
}

pub fn start<T: 'static+WebDriverHandler<U>,
             U: 'static+WebDriverExtensionRoute>(address: SocketAddr,
                                                 handler: T,
                                                 extension_routes:Vec<(Method, &str, U)>) {
    let (msg_send, msg_recv) = channel();

    let api = WebDriverHttpApi::new(extension_routes);
    let http_handler = HttpHandler::new(api, msg_send);
    let mut server = Server::http(address).unwrap();
    server.keep_alive(None);

    let builder = thread::Builder::new().name("webdriver dispatcher".to_string());
    builder.spawn(move || {
        let mut dispatcher = Dispatcher::new(handler);
        dispatcher.run(msg_recv)
    }).unwrap();
    server.handle(http_handler).unwrap();
}
<|endoftext|>


<commit_before>use std::net::{TcpListener, TcpStream};
use std::collections::HashMap;

use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};

use std::io::prelude::*;
use std::io::BufReader;

extern crate hmacsha1;
extern crate uuid;

use self::uuid::Uuid;
use client::Client;
use distributor::Distributor;

pub struct Player {
    client_idx: usize, //this is dynamic in the sense that it may be different on intial run
}

pub struct Server {
    clients: Vec<Client>, // this always grows
    players: HashMap<Uuid, Player>,
}

impl Server {
    pub fn new(ip: &str) {
        let listener = TcpListener::bind(ip).unwrap();

        let server = Server {
            clients: vec!(),
            players: HashMap::new(),
        };
        let server = Arc::new(Mutex::new(server));

        for s in listener.incoming() {
            match s {
                Ok(s) => {
                    let server = server.clone();
                    thread::spawn(|| Server::handler(server,s));
                },
                _ => {},
            }
        }
    }

    fn handler (mut server: Arc<Mutex<Server>>, mut s: TcpStream) {
        let mut cmd = [0;1];

        //new conn needs auth code
        let m = uuid::Uuid::new_v4();
        s.write_all(m.as_bytes());

        let mut client_idx = None;

        loop {
            if let Ok(_) = s.read_exact(&mut cmd) {
                match cmd[0] {
                    0 => { //login
                        if let Some(c) = Client::load(&mut s) {
                            let mut server = server.lock().unwrap();

                            let mut reg_key = None;
                            for (i,n) in server.clients.iter_mut().enumerate() {
                                if n.id == c.id {
                                    reg_key = Some(n.key);
                                    client_idx = Some(i);
                                    if let Ok(stmp) = s.try_clone() {
                                        n.stream = Some(Arc::new(Mutex::new(stmp)));
                                    }
                                    break
                                }
                            }

                            if let Some(key) = reg_key {
                                let hm = hmacsha1::hmac_sha1(&key, m.as_bytes());
                                if c.key == hm {
                                    server.players.insert(c.id,
                                                          Player {client_idx:client_idx.unwrap()});
                                    println!("login:{:?}",c.id);
                                    println!("total clients:{:?}",server.clients.len());
                                }
                                else {
                                    panic!("client invalid login {:?}", c)
                                }

                            }
                            else { panic!("client unregistered {:?}", c) }
                        }
                    },
                    1 => { //register
                        if let Some(c) = Client::load(&mut s) {
                            let mut server = server.lock().unwrap();

                            for n in server.clients.iter() {
                                if n.id == c.id { continue }
                            }

                            println!("registered:{:?}",c.id);
                            server.clients.push(c);
                        }
                    },
                    2 => { //chat
                        let mut text = String::new();
                        {
                            let mut bs = BufReader::new(&s);
                            bs.read_line(&mut text);
                        }

                        if text.chars().count() > 0 {
                            println!("chat-client:{:?}",text.trim());

                            //echo back
                            s.write_all(&[2]);
                            s.write_all(&text.as_bytes());
                        }
                    },
                    _ => panic!("cmd:{:?}",cmd)
                }
            }
        }

        println!("client dropped");
    }
}
<commit_msg>broadcast example<commit_after>use std::net::{TcpListener, TcpStream};
use std::collections::HashMap;

use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender};

use std::io::prelude::*;
use std::io::BufReader;

extern crate hmacsha1;
extern crate uuid;

use self::uuid::Uuid;
use client::Client;
use distributor::Distributor;
use distributor::Kind as DistKind;

pub struct Player {
    client_idx: usize, //this is dynamic in the sense that it may be different on intial run
}

pub struct Server {
    clients: Vec<Client>, // this always grows
    players: HashMap<Uuid, Player>,
    pub dist_tx: Sender<DistKind<TcpStream>>,
}

impl Server {
    pub fn new(ip: &str) {
        let listener = TcpListener::bind(ip).unwrap();

        let (dist_tx,mut dist) = Distributor::new();
        thread::spawn(move || dist.run());

        let server = Server {
            clients: vec!(),
            players: HashMap::new(),
            dist_tx: dist_tx,
        };
        let server = Arc::new(Mutex::new(server));

        for s in listener.incoming() {
            match s {
                Ok(s) => {
                    let server = server.clone();
                    thread::spawn(|| Server::handler(server,s));
                },
                _ => {},
            }
        }
    }

    fn handler (mut server: Arc<Mutex<Server>>, mut s: TcpStream) {
        let mut cmd = [0;1];

        //new conn needs auth code
        let m = uuid::Uuid::new_v4();
        s.write_all(m.as_bytes());

        let mut client_idx = None;

        loop {
            if let Ok(_) = s.read_exact(&mut cmd) {
                match cmd[0] {
                    0 => { //login
                        if let Some(c) = Client::load(&mut s) {
                            let mut server = server.lock().unwrap();

                            let mut reg_key = None;
                            for (i,n) in server.clients.iter_mut().enumerate() {
                                if n.id == c.id {
                                    reg_key = Some(n.key);
                                    client_idx = Some(i);

                                    break
                                }
                            }

                            if let Some(key) = reg_key {
                                let hm = hmacsha1::hmac_sha1(&key, m.as_bytes());
                                if c.key == hm {
                                    server.players.insert(c.id,
                                                          Player {client_idx:client_idx.unwrap()});

                                    if let Ok(stmp) = s.try_clone() {
                                        //n.stream = Some(Arc::new(Mutex::new(stmp)));
                                        server.dist_tx.send(DistKind::Add(c.id,stmp));
                                    }

                                    println!("login:{:?}",c.id);
                                    println!("total clients:{:?}",server.clients.len());
                                }
                                else {
                                    panic!("client invalid login {:?}", c)
                                }

                            }
                            else { panic!("client unregistered {:?}", c) }
                        }
                    },
                    1 => { //register
                        if let Some(c) = Client::load(&mut s) {
                            let mut server = server.lock().unwrap();

                            for n in server.clients.iter() {
                                if n.id == c.id { continue }
                            }

                            println!("registered:{:?}",c.id);
                            server.clients.push(c);
                        }
                    },
                    2 => { //chat
                        let mut text = String::new();
                        {
                            let mut bs = BufReader::new(&s);
                            bs.read_line(&mut text);
                        }

                        if text.chars().count() > 0 {
                            println!("chat-client:{:?}",text.trim());

                            //broadcast
                            let mut data = Vec::new();
                            data.push(2u8);
                            data.append(&mut text.into_bytes());

                            let mut server = server.lock().unwrap();
                            server.dist_tx.send(DistKind::Broadcast(data));
                        }
                    },
                    _ => panic!("cmd:{:?}",cmd)
                }
            }
        }

        println!("client dropped");
    }
}
<|endoftext|>


<commit_before>use super::structure::{Program,Condition,Command,Expression,Sensor};

pub trait Source {
	fn source(&self) -> String;
}

impl Source for Program {
	fn source(&self) -> String {
		match *self {
			Program::If(ref condition, ref left, ref right) => format!("iff!({},{},{})", condition.source(), left.source(), right.source()),
			Program::Command(ref command)                   => command.source(),
		}
	}
}

impl Source for Condition {
	fn source(&self) -> String {
		match *self {
			Condition::True                              => format!("T!()"),
			Condition::False                             => format!("F!()"),
			Condition::Not(ref condition)                => format!("not!({})", (*condition).source()),
			Condition::Or(ref left, ref right)           => format!("or!({},{})", (*left).source(), (*right).source()),
			Condition::And(ref left, ref right)          => format!("and!({},{})", (*left).source(), (*right).source()),

			Condition::Less(ref left, ref right)         => format!("less!({},{})", (*left).source(), (*right).source()),
			Condition::LessEqual(ref left, ref right)    => format!("less_equal!({},{})", (*left).source(), (*right).source()),
			Condition::Equal(ref left, ref right)        => format!("equal!({},{})", (*left).source(), (*right).source()),
			Condition::GreaterEqual(ref left, ref right) => format!("greater_equal!({},{})", (*left).source(), (*right).source()),
			Condition::Greater(ref left, ref right)      => format!("greater!({},{})", (*left).source(), (*right).source()),
		}
	}
}

impl Source for Expression {
	fn source(&self) -> String {
		match *self {
			Expression::Constant(value)               => format!("constant!({:.*})", 4, value),
			Expression::Sensor(ref sensor)            => sensor.source(),
			Expression::Plus(ref left, ref right)     => format!("plus!({},{})", (*left).source(), (*right).source()),
			Expression::Minus(ref left, ref right)    => format!("minus!({},{})", (*left).source(), (*right).source()),
			Expression::Multiply(ref left, ref right) => format!("multiply!({},{})", (*left).source(), (*right).source()),
			Expression::Divide(ref left, ref right)   => format!("divide!({},{})", (*left).source(), (*right).source()),
		}
	}
}

impl Source for Sensor {
	fn source(&self) -> String {
		match *self {
			Sensor::X  => format!("x!()"),
			Sensor::Y  => format!("u!()"),
			Sensor::Vx => format!("vx!()"),
			Sensor::Vy => format!("vy!()"),
			Sensor::O  => format!("o!()"),
			Sensor::W  => format!("w!()"),
		}
	}
}

impl Source for Command {
	fn source(&self) -> String {
		match *self {
			Command::Skip  => format!("skip!()"),
			Command::Left  => format!("left!()"),
			Command::Right => format!("right!()"),
			Command::Up    => format!("up!()"),
		}
	}
}<commit_msg>Create test to check behavior of source<commit_after>use super::structure::{Program,Condition,Command,Expression,Sensor};

pub trait Source {
	fn source(&self) -> String;
}

impl Source for Program {
	fn source(&self) -> String {
		match *self {
			Program::If(ref condition, ref left, ref right) => format!("iff!({},{},{})", condition.source(), left.source(), right.source()),
			Program::Command(ref command)                   => command.source(),
		}
	}
}

impl Source for Condition {
	fn source(&self) -> String {
		match *self {
			Condition::True                              => format!("T!()"),
			Condition::False                             => format!("F!()"),
			Condition::Not(ref condition)                => format!("not!({})", (*condition).source()),
			Condition::Or(ref left, ref right)           => format!("or!({},{})", (*left).source(), (*right).source()),
			Condition::And(ref left, ref right)          => format!("and!({},{})", (*left).source(), (*right).source()),

			Condition::Less(ref left, ref right)         => format!("less!({},{})", (*left).source(), (*right).source()),
			Condition::LessEqual(ref left, ref right)    => format!("less_equal!({},{})", (*left).source(), (*right).source()),
			Condition::Equal(ref left, ref right)        => format!("equal!({},{})", (*left).source(), (*right).source()),
			Condition::GreaterEqual(ref left, ref right) => format!("greater_equal!({},{})", (*left).source(), (*right).source()),
			Condition::Greater(ref left, ref right)      => format!("greater!({},{})", (*left).source(), (*right).source()),
		}
	}
}

impl Source for Expression {
	fn source(&self) -> String {
		match *self {
			Expression::Constant(value)               => format!("constant!({:.*})", 4, value),
			Expression::Sensor(ref sensor)            => sensor.source(),
			Expression::Plus(ref left, ref right)     => format!("plus!({},{})", (*left).source(), (*right).source()),
			Expression::Minus(ref left, ref right)    => format!("minus!({},{})", (*left).source(), (*right).source()),
			Expression::Multiply(ref left, ref right) => format!("multiply!({},{})", (*left).source(), (*right).source()),
			Expression::Divide(ref left, ref right)   => format!("divide!({},{})", (*left).source(), (*right).source()),
		}
	}
}

impl Source for Sensor {
	fn source(&self) -> String {
		match *self {
			Sensor::X  => format!("x!()"),
			Sensor::Y  => format!("u!()"),
			Sensor::Vx => format!("vx!()"),
			Sensor::Vy => format!("vy!()"),
			Sensor::O  => format!("o!()"),
			Sensor::W  => format!("w!()"),
		}
	}
}

impl Source for Command {
	fn source(&self) -> String {
		match *self {
			Command::Skip  => format!("skip!()"),
			Command::Left  => format!("left!()"),
			Command::Right => format!("right!()"),
			Command::Up    => format!("up!()"),
		}
	}
}

#[test]
fn should_correctly_source_programs() {
	assert_eq!("iff!(T!(),skip!(),left!())",
		Program::If(Condition::True, Box::new(Program::Command(Command::Skip)), Box::new(Program::Command(Command::Left))).source());
	assert_eq!("skip!()", Program::Command(Command::Skip).source());
}

#[test]
fn should_correctly_source_conditions() {
	assert_eq!("T!()", Condition::True.source());
	assert_eq!("F!()", Condition::False.source());
	assert_eq!("not!(T!())", Condition::Not(Box::new(Condition::True)).source());
	assert_eq!("or!(T!(),F!())", Condition::Or(Box::new(Condition::True), Box::new(Condition::False)).source());
	assert_eq!("and!(F!(),T!())", Condition::And(Box::new(Condition::False), Box::new(Condition::True)).source());
	assert_eq!("less!(constant!(1.0000),constant!(2.0000))",
		Condition::Less(Box::new(Expression::Constant(1.0)), Box::new(Expression::Constant(2.0))).source());
	assert_eq!("less_equal!(constant!(1.0000),constant!(2.0000))",
		Condition::LessEqual(Box::new(Expression::Constant(1.0)), Box::new(Expression::Constant(2.0))).source());
	assert_eq!("equal!(constant!(1.0000),constant!(2.0000))",
		Condition::Equal(Box::new(Expression::Constant(1.0)), Box::new(Expression::Constant(2.0))).source());
	assert_eq!("greater_equal!(constant!(1.0000),constant!(2.0000))",
		Condition::GreaterEqual(Box::new(Expression::Constant(1.0)), Box::new(Expression::Constant(2.0))).source());
	assert_eq!("greater!(constant!(1.0000),constant!(2.0000))",
		Condition::Greater(Box::new(Expression::Constant(1.0)), Box::new(Expression::Constant(2.0))).source());
}

#[test]
fn should_correctly_source_expressions() {
	assert_eq!("constant!(1.0000)", Expression::Constant(1.0).source());
	assert_eq!("vx!()", Expression::Sensor(Sensor::Vx).source());
	assert_eq!("plus!(constant!(1.0000),vy!())",
		Expression::Plus(Box::new(Expression::Constant(1.0)),Box::new(Expression::Sensor(Sensor::Vy))).source());
	assert_eq!("minus!(constant!(1.0000),constant!(2.0000))",
		Expression::Minus(Box::new(Expression::Constant(1.0)),Box::new(Expression::Constant(2.0))).source());
	assert_eq!("multiply!(constant!(1.0000),constant!(2.0000))",
		Expression::Multiply(Box::new(Expression::Constant(1.0)),Box::new(Expression::Constant(2.0))).source());
	assert_eq!("divide!(constant!(1.0000),constant!(2.0000))",
		Expression::Divide(Box::new(Expression::Constant(1.0)),Box::new(Expression::Constant(2.0))).source());
}

#[test]
fn should_correctly_source_sensors() {
	assert_eq!("x!()",  Sensor::X.source());
	assert_eq!("u!()",  Sensor::Y.source());
	assert_eq!("vx!()", Sensor::Vx.source());
	assert_eq!("vy!()", Sensor::Vy.source());
	assert_eq!("o!()",  Sensor::O.source());
	assert_eq!("w!()",  Sensor::W.source());
}

#[test]
fn should_correctly_source_commands() {
	assert_eq!("skip!()",  Command::Skip.source());
	assert_eq!("left!()",  Command::Left.source());
	assert_eq!("right!()", Command::Right.source());
	assert_eq!("up!()",    Command::Up.source());
}<|endoftext|>


<commit_before>use std::collections::HashMap;

use ast::Expression;
use error::{Error, ErrorKind, ErrorLevel};
use to_javascript::ToJavaScript;

type BuiltinMap = HashMap<&'static str, fn(&Vec<Box<Expression>>) -> Result<String, Error>>;

lazy_static! {
    pub static ref BUILTINS: BuiltinMap = {
        // The type definition is required to prevent compile errors
        let mut map: BuiltinMap = HashMap::new();

        map.insert("if", builtin_if);

        map
    };
}

pub fn builtin_if(args: &Vec<Box<Expression>>) -> Result<String, Error> {
    // TODO: Remove unwraps
    match args.len() {
        0 => {
            Err(Error(ErrorLevel::Error,
                      ErrorKind::TooFewArguments,
                      "Too Few Arguments applied for if"))
        }
        1 => {
            Err(Error(ErrorLevel::Error,
                      ErrorKind::TooFewArguments,
                      "No expression applied for condition"))
        }
        2 => {
            Ok(format!("(if {} {{ {} }})",
                       args[0].eval().unwrap(),
                       args[1].eval().unwrap()))
        }
        3 => {
            Ok(format!("(if {} {{ {} }} else {{ {} }})",
                       args[0].eval().unwrap(),
                       args[1].eval().unwrap(),
                       args[2].eval().unwrap()))
        }
        _ => panic!("Unknown number of arguments supplied to if-statement"),
    }
}
<commit_msg>Remove whitespace<commit_after>use std::collections::HashMap;

use ast::Expression;
use error::{Error, ErrorKind, ErrorLevel};
use to_javascript::ToJavaScript;

type BuiltinMap = HashMap<&'static str, fn(&Vec<Box<Expression>>) -> Result<String, Error>>;

lazy_static! {
    pub static ref BUILTINS: BuiltinMap = {
        // The type definition is required to prevent compile errors
        let mut map: BuiltinMap = HashMap::new();

        map.insert("if", builtin_if);

        map
    };
}

pub fn builtin_if(args: &Vec<Box<Expression>>) -> Result<String, Error> {
    // TODO: Remove unwraps
    match args.len() {
        0 => {
            Err(Error(ErrorLevel::Error,
                      ErrorKind::TooFewArguments,
                      "Too Few Arguments applied for if"))
        }
        1 => {
            Err(Error(ErrorLevel::Error,
                      ErrorKind::TooFewArguments,
                      "No expression applied for condition"))
        }
        2 => {
            Ok(format!("(if {} {{ {} }})",
                       args[0].eval().unwrap(),
                       args[1].eval().unwrap()))
        }
        3 => {
            Ok(format!("(if {} {{ {} }} else {{ {} }})",
                       args[0].eval().unwrap(),
                       args[1].eval().unwrap(),
                       args[2].eval().unwrap()))
        }
        _ => panic!("Unknown number of arguments supplied to if-statement"),
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use ast::Expression;
use error::{Error, ErrorKind, ErrorLevel};
use to_javascript::ToJavaScript;

type BuiltinMap = HashMap<&'static str, fn(&Vec<Box<Expression>>) -> Result<String, Error>>;

lazy_static! {
    pub static ref BUILTINS: BuiltinMap = {
        // The type definition is required to prevent compile errors
        let mut map: BuiltinMap = HashMap::new();

        map.insert("if", builtin_if);

        map
    };
}

pub fn builtin_if(args: &Vec<Box<Expression>>) -> Result<String, Error> {
    // TODO: Remove unwraps
    match args.len() {
        0 => {
            Err(Error(ErrorLevel::Error,
                      ErrorKind::TooFewArguments,
                      "Too Few Arguments applied for if"))
        }
        1 => {
            Err(Error(ErrorLevel::Error,
                      ErrorKind::TooFewArguments,
                      "No expression applied for condition"))
        }
        2 => {
            Ok(format!("(if {} {{ {} }})",
                       args[0].eval().unwrap(),
                       args[1].eval().unwrap()))
        }
        3 => {
            Ok(format!("(if {} {{ {} }} else {{ {} }})",
                       args[0].eval().unwrap(),
                       args[1].eval().unwrap(),
                       args[2].eval().unwrap()))
        }
        _ => panic!("Unknown number of arguments supplied to if-statement"),
    }
}
<commit_msg>Typos, add brackets around conditions.<commit_after>use std::collections::HashMap;

use ast::Expression;
use error::{Error, ErrorKind, ErrorLevel};
use to_javascript::ToJavaScript;

type BuiltinMap = HashMap<&'static str, fn(&Vec<Box<Expression>>) -> Result<String, Error>>;

lazy_static! {
    pub static ref BUILTINS: BuiltinMap = {
        // The type definition is required to prevent compile errors
        let mut map: BuiltinMap = HashMap::new();

        map.insert("if", builtin_if);

        map
    };
}

pub fn builtin_if(args: &Vec<Box<Expression>>) -> Result<String, Error> {
    // TODO: Remove unwraps
    match args.len() {
        0 => {
            Err(Error(ErrorLevel::Error,
                      ErrorKind::TooFewArguments,
                      "Too few Arguments applied for if"))
        }
        1 => {
            Err(Error(ErrorLevel::Error,
                      ErrorKind::TooFewArguments,
                      "No expression applied for condition"))
        }
        2 => {
            Ok(format!("(if ({}) {{ {} }})",
                       args[0].eval().unwrap(),
                       args[1].eval().unwrap()))
        }
        3 => {
            Ok(format!("(if ({}) {{ {} }} else {{ {} }})",
                       args[0].eval().unwrap(),
                       args[1].eval().unwrap(),
                       args[2].eval().unwrap()))
        }
        _ => panic!("Unknown number of arguments supplied to if-statement"),
    }
}
<|endoftext|>


<commit_before>use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo};
use frame::frame_parser;
use utility::{
  ErrorKind, ByteStream, ReadStream, StreamProducer, many_metadata,
};

use std::io;
use std::usize;
use std::fs::File;

/// FLAC stream that decodes and hold file information.
pub struct Stream
 {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  producer: P,
  output: Vec<i32>,
}

/// Alias for a FLAC stream produced from `Read`.
pub type StreamReader<R>  = Stream<ReadStream<R>>;

/// Alias for a FLAC stream produced from a byte stream buffer.
pub type StreamBuffer<'a> = Stream<ByteStream<'a>>;

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  #[inline]
  pub fn new<R: io::Read>(reader: R) -> Result<StreamReader<R>, ErrorKind> {
    let producer = ReadStream::new(reader);

    Stream::from_stream_producer(producer)
  }

  /// Returns information for the current stream.
  #[inline]
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  #[inline]
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_file(filename: &str) -> Result<StreamReader<File>, ErrorKind> {
    File::open(filename).map_err(|e| ErrorKind::IO(e.kind()))
                        .and_then(|file| {
      let producer = ReadStream::new(file);

      Stream::from_stream_producer(producer)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_buffer(buffer: &[u8]) -> Result<StreamBuffer, ErrorKind> {
    let producer = ByteStream::new(buffer);

    Stream::from_stream_producer(producer)
  }

  fn from_stream_producer(mut producer: P) -> Result<Self, ErrorKind> {
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

    many_metadata(&mut producer, |block| {
      if let metadata::Data::StreamInfo(info) = block.data {
        stream_info = info;
      } else {
        metadata.push(block);
      }
    }).map(|_| {
      Stream {
        info: stream_info,
        metadata: metadata,
        producer: producer,
        output: Vec::new(),
      }
    })
  }

  /// Returns an iterator over the decoded samples.
  #[inline]
  pub fn iter(&mut self) -> Iter
 {
    let samples_left = self.info.total_samples;

    if self.output.is_empty() {
      let channels    = self.info.channels as usize;
      let block_size  = self.info.max_block_size as usize;
      let output_size = block_size * channels;

      self.output.reserve_exact(output_size);

      unsafe { self.output.set_len(output_size) }
    }

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }

  fn next_frame<'a>(&'a mut self) -> Option<usize> {
    let stream_info = &self.info;
    let buffer      = &mut self.output;

    loop {
      match self.producer.parse(|i| frame_parser(i, stream_info, buffer)) {
        Ok(frame)                  => {
          let channels    = frame.header.channels as usize;
          let block_size  = frame.header.block_size as usize;
          let mut channel = 0;

          for subframe in &frame.subframes[0..channels] {
            let start  = channel * block_size;
            let end    = (channel + 1) * block_size;
            let output = &mut buffer[start..end];

            subframe::decode(&subframe, block_size, output);

            channel += 1;
          }

          frame::decode(frame.header.channel_assignment, buffer);

          return Some(block_size);
        }
        Err(ErrorKind::EndOfInput) => return None,
        Err(ErrorKind::Continue)   => continue,
        Err(_)                     => return None,
      }
    }
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a, P> where P: 'a + StreamProducer {
  stream: &'a mut Stream
,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a, P> Iterator for Iter<'a, P> where P: StreamProducer {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      if let Some(block_size) = self.stream.next_frame() {
        self.sample_index = 0;
        self.block_size   = block_size;
      } else {
        return None;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel += 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
      self.samples_left -= 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a, P> IntoIterator for &'a mut Stream

 where P: StreamProducer {
  type Item     = i32;
  type IntoIter = Iter<'a, P>;

  #[inline]
  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<commit_msg>Remove no longer needed lifetime annotation<commit_after>use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo};
use frame::frame_parser;
use utility::{
  ErrorKind, ByteStream, ReadStream, StreamProducer, many_metadata,
};

use std::io;
use std::usize;
use std::fs::File;

/// FLAC stream that decodes and hold file information.
pub struct Stream
 {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  producer: P,
  output: Vec<i32>,
}

/// Alias for a FLAC stream produced from `Read`.
pub type StreamReader<R>  = Stream<ReadStream<R>>;

/// Alias for a FLAC stream produced from a byte stream buffer.
pub type StreamBuffer<'a> = Stream<ByteStream<'a>>;

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  #[inline]
  pub fn new<R: io::Read>(reader: R) -> Result<StreamReader<R>, ErrorKind> {
    let producer = ReadStream::new(reader);

    Stream::from_stream_producer(producer)
  }

  /// Returns information for the current stream.
  #[inline]
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  #[inline]
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_file(filename: &str) -> Result<StreamReader<File>, ErrorKind> {
    File::open(filename).map_err(|e| ErrorKind::IO(e.kind()))
                        .and_then(|file| {
      let producer = ReadStream::new(file);

      Stream::from_stream_producer(producer)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_buffer(buffer: &[u8]) -> Result<StreamBuffer, ErrorKind> {
    let producer = ByteStream::new(buffer);

    Stream::from_stream_producer(producer)
  }

  fn from_stream_producer(mut producer: P) -> Result<Self, ErrorKind> {
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

    many_metadata(&mut producer, |block| {
      if let metadata::Data::StreamInfo(info) = block.data {
        stream_info = info;
      } else {
        metadata.push(block);
      }
    }).map(|_| {
      Stream {
        info: stream_info,
        metadata: metadata,
        producer: producer,
        output: Vec::new(),
      }
    })
  }

  /// Returns an iterator over the decoded samples.
  #[inline]
  pub fn iter(&mut self) -> Iter
 {
    let samples_left = self.info.total_samples;

    if self.output.is_empty() {
      let channels    = self.info.channels as usize;
      let block_size  = self.info.max_block_size as usize;
      let output_size = block_size * channels;

      self.output.reserve_exact(output_size);

      unsafe { self.output.set_len(output_size) }
    }

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }

  fn next_frame(&mut self) -> Option<usize> {
    let stream_info = &self.info;
    let buffer      = &mut self.output;

    loop {
      match self.producer.parse(|i| frame_parser(i, stream_info, buffer)) {
        Ok(frame)                  => {
          let channels    = frame.header.channels as usize;
          let block_size  = frame.header.block_size as usize;
          let mut channel = 0;

          for subframe in &frame.subframes[0..channels] {
            let start  = channel * block_size;
            let end    = (channel + 1) * block_size;
            let output = &mut buffer[start..end];

            subframe::decode(&subframe, block_size, output);

            channel += 1;
          }

          frame::decode(frame.header.channel_assignment, buffer);

          return Some(block_size);
        }
        Err(ErrorKind::EndOfInput) => return None,
        Err(ErrorKind::Continue)   => continue,
        Err(_)                     => return None,
      }
    }
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a, P> where P: 'a + StreamProducer {
  stream: &'a mut Stream
,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a, P> Iterator for Iter<'a, P> where P: StreamProducer {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      if let Some(block_size) = self.stream.next_frame() {
        self.sample_index = 0;
        self.block_size   = block_size;
      } else {
        return None;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel += 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
      self.samples_left -= 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a, P> IntoIterator for &'a mut Stream

 where P: StreamProducer {
  type Item     = i32;
  type IntoIter = Iter<'a, P>;

  #[inline]
  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<|endoftext|>


<commit_before>// 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 std::fmt;
use super::attachinfo::SBAttachInfo;
use super::broadcaster::SBBroadcaster;
use super::debugger::SBDebugger;
use super::error::SBError;
use super::filespec::SBFileSpec;
use super::launchinfo::SBLaunchInfo;
use super::module::SBModule;
use super::modulespec::SBModuleSpec;
use super::platform::SBPlatform;
use super::process::SBProcess;
use super::stream::SBStream;
use super::DescriptionLevel;
use sys;

/// The target program running under the debugger.
///
/// # Process Management
///
/// Starting a debug session is done by launching the target,
/// attaching to a running process, or loading a core file.
///
/// ## Launching
///
/// Launching a process can be done by creating and filling
/// out an [`SBLaunchInfo`] and calling [`launch`].
///
///
/// ## Attaching
///
/// Attaching to a process can be done by creating and filling
/// out an [`SBAttachInfo`] and calling [`attach`].
///
/// ```no_run
/// use lldb::{lldb_pid_t, SBAttachInfo, SBError, SBProcess, SBTarget};
/// fn attach_to_pid(target: &SBTarget, pid: lldb_pid_t) -> Result<SBProcess, SBError> {
///     let attach_info = SBAttachInfo::new_with_pid(pid);
///     // Probably want to set up a listener here.
///     target.attach(attach_info)
/// }
/// ```
///
/// ## Core Files
///
/// ...
///
/// # Breakpoints and Watchpoints
///
/// ...
///
/// # Modules
///
/// ...
///
/// # Events
///
/// ...
///
/// [`SBLaunchInfo`]: struct.SBLaunchInfo.html
/// [`launch`]: #method.launch
/// [`SBAttachInfo`]: struct.SBAttachInfo.html
/// [`attach`]: #method.attach
pub struct SBTarget {
    /// The underlying raw `SBTargetRef`.
    pub raw: sys::SBTargetRef,
}

impl SBTarget {
    /// Construct a new `SBTarget`.
    pub fn wrap(raw: sys::SBTargetRef) -> SBTarget {
        SBTarget { raw: raw }
    }

    /// Construct a new `Some(SBTarget)` or `None`.
    pub fn maybe_wrap(raw: sys::SBTargetRef) -> Option<SBTarget> {
        if unsafe { sys::SBTargetIsValid(raw) != 0 } {
            Some(SBTarget { raw: raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBTarget` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBTargetIsValid(self.raw) != 0 }
    }

    /// Get the [`SBPlatform`] associated with this target.
    ///
    /// After return, the platform object should be checked for validity.
    ///
    /// [`SBPlatform`]: strut.SBPlatform.html
    pub fn platform(&self) -> SBPlatform {
        unsafe { SBPlatform { raw: sys::SBTargetGetPlatform(self.raw) } }
    }

    /// Get the [`SBProcess`] associated with this target.
    ///
    /// [`SBProcess`]: strut.SBProcess.html
    pub fn process(&self) -> SBProcess {
        unsafe { SBProcess { raw: sys::SBTargetGetProcess(self.raw) } }
    }

    /// Launch a target for debugging.
    pub fn launch(&self, launch_info: SBLaunchInfo) -> Result<SBProcess, SBError> {
        let error: SBError = SBError::new();
        let process =
            SBProcess::wrap(unsafe { sys::SBTargetLaunch2(self.raw, launch_info.raw, error.raw) });
        if error.is_success() {
            Ok(process)
        } else {
            Err(error)
        }
    }

    #[allow(missing_docs)]
    pub fn attach(&self, attach_info: SBAttachInfo) -> Result<SBProcess, SBError> {
        let error: SBError = SBError::new();
        let process =
            SBProcess::wrap(unsafe { sys::SBTargetAttach(self.raw, attach_info.raw, error.raw) });
        if error.is_success() {
            Ok(process)
        } else {
            Err(error)
        }
    }

    /// Get a filespec for the executable.
    pub fn executable(&self) -> Option<SBFileSpec> {
        SBFileSpec::maybe_wrap(unsafe { sys::SBTargetGetExecutable(self.raw) })
    }

    /// Add a module to the target.
    pub fn add_module(&self, module: &SBModule) -> bool {
        unsafe { sys::SBTargetAddModule(self.raw, module.raw) != 0 }
    }

    /// Add a module to the target using an `SBModuleSpec`.
    pub fn add_module_spec(&self, module_spec: &SBModuleSpec) -> Option<SBModule> {
        SBModule::maybe_wrap(unsafe { sys::SBTargetAddModule4(self.raw, module_spec.raw) })
    }

    /// Remove a module from the target.
    pub fn remove_module(&self, module: &SBModule) -> bool {
        unsafe { sys::SBTargetRemoveModule(self.raw, module.raw) != 0 }
    }

    /// Get the debugger controlling this target.
    pub fn debugger(&self) -> SBDebugger {
        SBDebugger { raw: unsafe { sys::SBTargetGetDebugger(self.raw) } }
    }

    /// Find the module for the given `SBFileSpec`.
    pub fn find_module(&self, file_spec: &SBFileSpec) -> Option<SBModule> {
        SBModule::maybe_wrap(unsafe { sys::SBTargetFindModule(self.raw, file_spec.raw) })
    }

    #[allow(missing_docs)]
    pub fn broadcaster(&self) -> SBBroadcaster {
        SBBroadcaster::wrap(unsafe { sys::SBTargetGetBroadcaster(self.raw) })
    }
}

impl fmt::Debug for SBTarget {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBTargetGetDescription(self.raw, stream.raw, DescriptionLevel::Brief) };
        write!(fmt, "SBTarget {{ {} }}", stream.data())
    }
}

impl Drop for SBTarget {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBTarget(self.raw) };
    }
}
<commit_msg>Add code example for launching.<commit_after>// 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 std::fmt;
use super::attachinfo::SBAttachInfo;
use super::broadcaster::SBBroadcaster;
use super::debugger::SBDebugger;
use super::error::SBError;
use super::filespec::SBFileSpec;
use super::launchinfo::SBLaunchInfo;
use super::module::SBModule;
use super::modulespec::SBModuleSpec;
use super::platform::SBPlatform;
use super::process::SBProcess;
use super::stream::SBStream;
use super::DescriptionLevel;
use sys;

/// The target program running under the debugger.
///
/// # Process Management
///
/// Starting a debug session is done by launching the target,
/// attaching to a running process, or loading a core file.
///
/// ## Launching
///
/// Launching a process can be done by creating and filling
/// out an [`SBLaunchInfo`] and calling [`launch`].
///
/// ```no_run
/// use lldb::*;
/// fn launch_target(target: &SBTarget) -> Result<SBProcess, SBError> {
///     let launch_info = SBLaunchInfo::new();
///     launch_info.set_launch_flags(LAUNCH_FLAG_STOP_AT_ENTRY);
///     // Probably want to set up a listener here.
///     target.launch(launch_info)
/// }
/// ```
///
/// ## Attaching
///
/// Attaching to a process can be done by creating and filling
/// out an [`SBAttachInfo`] and calling [`attach`].
///
/// ```no_run
/// use lldb::{lldb_pid_t, SBAttachInfo, SBError, SBProcess, SBTarget};
/// fn attach_to_pid(target: &SBTarget, pid: lldb_pid_t) -> Result<SBProcess, SBError> {
///     let attach_info = SBAttachInfo::new_with_pid(pid);
///     // Probably want to set up a listener here.
///     target.attach(attach_info)
/// }
/// ```
///
/// ## Core Files
///
/// ...
///
/// # Breakpoints and Watchpoints
///
/// ...
///
/// # Modules
///
/// ...
///
/// # Events
///
/// ...
///
/// [`SBLaunchInfo`]: struct.SBLaunchInfo.html
/// [`launch`]: #method.launch
/// [`SBAttachInfo`]: struct.SBAttachInfo.html
/// [`attach`]: #method.attach
pub struct SBTarget {
    /// The underlying raw `SBTargetRef`.
    pub raw: sys::SBTargetRef,
}

impl SBTarget {
    /// Construct a new `SBTarget`.
    pub fn wrap(raw: sys::SBTargetRef) -> SBTarget {
        SBTarget { raw: raw }
    }

    /// Construct a new `Some(SBTarget)` or `None`.
    pub fn maybe_wrap(raw: sys::SBTargetRef) -> Option<SBTarget> {
        if unsafe { sys::SBTargetIsValid(raw) != 0 } {
            Some(SBTarget { raw: raw })
        } else {
            None
        }
    }

    /// Check whether or not this is a valid `SBTarget` value.
    pub fn is_valid(&self) -> bool {
        unsafe { sys::SBTargetIsValid(self.raw) != 0 }
    }

    /// Get the [`SBPlatform`] associated with this target.
    ///
    /// After return, the platform object should be checked for validity.
    ///
    /// [`SBPlatform`]: strut.SBPlatform.html
    pub fn platform(&self) -> SBPlatform {
        unsafe { SBPlatform { raw: sys::SBTargetGetPlatform(self.raw) } }
    }

    /// Get the [`SBProcess`] associated with this target.
    ///
    /// [`SBProcess`]: strut.SBProcess.html
    pub fn process(&self) -> SBProcess {
        unsafe { SBProcess { raw: sys::SBTargetGetProcess(self.raw) } }
    }

    /// Launch a target for debugging.
    pub fn launch(&self, launch_info: SBLaunchInfo) -> Result<SBProcess, SBError> {
        let error: SBError = SBError::new();
        let process =
            SBProcess::wrap(unsafe { sys::SBTargetLaunch2(self.raw, launch_info.raw, error.raw) });
        if error.is_success() {
            Ok(process)
        } else {
            Err(error)
        }
    }

    #[allow(missing_docs)]
    pub fn attach(&self, attach_info: SBAttachInfo) -> Result<SBProcess, SBError> {
        let error: SBError = SBError::new();
        let process =
            SBProcess::wrap(unsafe { sys::SBTargetAttach(self.raw, attach_info.raw, error.raw) });
        if error.is_success() {
            Ok(process)
        } else {
            Err(error)
        }
    }

    /// Get a filespec for the executable.
    pub fn executable(&self) -> Option<SBFileSpec> {
        SBFileSpec::maybe_wrap(unsafe { sys::SBTargetGetExecutable(self.raw) })
    }

    /// Add a module to the target.
    pub fn add_module(&self, module: &SBModule) -> bool {
        unsafe { sys::SBTargetAddModule(self.raw, module.raw) != 0 }
    }

    /// Add a module to the target using an `SBModuleSpec`.
    pub fn add_module_spec(&self, module_spec: &SBModuleSpec) -> Option<SBModule> {
        SBModule::maybe_wrap(unsafe { sys::SBTargetAddModule4(self.raw, module_spec.raw) })
    }

    /// Remove a module from the target.
    pub fn remove_module(&self, module: &SBModule) -> bool {
        unsafe { sys::SBTargetRemoveModule(self.raw, module.raw) != 0 }
    }

    /// Get the debugger controlling this target.
    pub fn debugger(&self) -> SBDebugger {
        SBDebugger { raw: unsafe { sys::SBTargetGetDebugger(self.raw) } }
    }

    /// Find the module for the given `SBFileSpec`.
    pub fn find_module(&self, file_spec: &SBFileSpec) -> Option<SBModule> {
        SBModule::maybe_wrap(unsafe { sys::SBTargetFindModule(self.raw, file_spec.raw) })
    }

    #[allow(missing_docs)]
    pub fn broadcaster(&self) -> SBBroadcaster {
        SBBroadcaster::wrap(unsafe { sys::SBTargetGetBroadcaster(self.raw) })
    }
}

impl fmt::Debug for SBTarget {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBTargetGetDescription(self.raw, stream.raw, DescriptionLevel::Brief) };
        write!(fmt, "SBTarget {{ {} }}", stream.data())
    }
}

impl Drop for SBTarget {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBTarget(self.raw) };
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nicholas Bishop
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ops::{Add, Div, Mul, Sub};

/// Vector with three f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Vec3f {
    /// Create a Vec3f from three components
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x,
                y: y,
                z: z }
    }

    /// Create a Vec3f with all components set to the same scalar
    pub fn from_scalar<T: CastF32>(s: T) -> Vec3f {
        let f = s.as_f32();
        Vec3f {
            x: f,
            y: f,
            z: f
        }
    }

    /// Squared length of the vector
    pub fn magnitude_squared(&self) -> f32 {
        dot3(*self, *self)
    }

    /// Length of the vector
    pub fn magnitude(&self) -> f32 {
        self.magnitude_squared().sqrt()
    }

    /// Create a normalized copy, or None if the magnitude is zero
    pub fn normalized(&self) -> Option<Vec3f> {
        let m = self.magnitude();
        if m == 0.0 {
            None
        }
        else {
            let f = 1.0 / m;
            Some((*self) * f)
        }
    }
}

/// Vec3f(0.0, 0.0, 0.0)
pub const ZERO_3F: Vec3f = Vec3f { x: 0.0, y: 0.0, z: 0.0 };

/// Convert a numeric type to an f32
pub trait CastF32 { fn as_f32(&self) -> f32; }

impl CastF32 for f32 { fn as_f32(&self) -> f32 { *self } }
impl CastF32 for f64 { fn as_f32(&self) -> f32 { *self as f32 } }

impl CastF32 for i8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for isize { fn as_f32(&self) -> f32 { *self as f32 } }

impl CastF32 for u8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for usize { fn as_f32(&self) -> f32 { *self as f32 } }

/// Create a Vec3f from x, y, and z inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec3f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec3f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec3f<X: CastF32, Y: CastF32, Z: CastF32>(x: X, y: Y, z: Z) -> Vec3f {
    Vec3f { x: x.as_f32(), y: y.as_f32(), z: z.as_f32() }
}

/// Inner product of two Vec3f inputs
pub fn dot3(a: Vec3f, b: Vec3f) -> f32 {
    let v = a * b;
    v.x + v.y + v.z
}

/// Cross product of two Vec3f inputs
pub fn cross(a: Vec3f, b: Vec3f) -> Vec3f {
    Vec3f::new(a.y * b.z - a.z * b.y,
               a.z * b.x - a.x * b.z,
               a.x * b.y - a.y * b.x)
}

/// Distance between two points
pub fn distance3(a: Vec3f, b: Vec3f) -> f32 {
    (a - b).magnitude()
}

/// Linearly interpolate between two points by the factor `t`. When
/// `t` is zero the result is `p0`, and when `t` is one the result is
/// `p1`. The range of `t` is not clamped.
pub fn lerp3(p0: &Vec3f, p1: &Vec3f, t: f32) -> Vec3f {
    let n = 1.0 - t;
    Vec3f::new(p0.x * n + p1.x * t,
               p0.y * n + p1.y * t,
               p0.z * n + p1.z * t)
}

impl Add for Vec3f {
    type Output = Vec3f;
    fn add(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x + v.x, self.y + v.y, self.z + v.z)
    }
}

impl Add<f32> for Vec3f {
    type Output = Vec3f;
    fn add(self, s: f32) -> Vec3f {
        Vec3f::new(self.x + s, self.y + s, self.z + s)
    }
}

impl Div for Vec3f {
    type Output = Vec3f;
    fn div(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x / v.x, self.y / v.y, self.z / v.z)
    }
}

impl Mul<Vec3f> for Vec3f {
    type Output = Vec3f;
    fn mul(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x * v.x, self.y * v.y, self.z * v.z)
    }
}

impl Mul<f32> for Vec3f {
    type Output = Vec3f;
    fn mul(self, f: f32) -> Vec3f {
        Vec3f::new(self.x * f, self.y * f, self.z * f)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x - v.x, self.y - v.y, self.z - v.z)
    }
}

impl Sub<f32> for Vec3f {
    type Output = Vec3f;
    fn sub(self, s: f32) -> Vec3f {
        Vec3f::new(self.x - s, self.y - s, self.z - s)
    }
}

#[test]
fn test_vec3f_create() {
    vec3f(1.0f32, 2, 3i32);
    assert!(Vec3f::from_scalar(1) == vec3f(1, 1, 1));
}

#[test]
fn test_vec3f_magnitude() {
    let v = vec3f(-4, 0, 0);
    assert!(v.magnitude_squared() == 16.0);
    assert!(v.magnitude() == 4.0);
}

#[test]
fn test_vec3f_distance() {
    assert!(distance3(vec3f(0, -4, 0), vec3f(0, 4, 0)) == 8.0);
}

#[test]
fn test_vec3f_normalized() {
    assert_eq!(vec3f(0, 0, 0).normalized(), None);
    assert_eq!(vec3f(0.5, 0, 0).normalized(), Some(vec3f(1, 0, 0)));
}

#[test]
fn test_vec3f_arithmetic() {
    let a = vec3f(1, 2, 3);
    let b = vec3f(4, 5, 6);
    assert!(a + b == vec3f(5, 7, 9));
    assert!(a - b == vec3f(-3, -3, -3));
    assert!(a * b == vec3f(4, 10, 18));
    assert!(a / b == vec3f(0.25, 2.0 / 5.0, 0.5));
}

#[test]
fn test_vec3f_dot() {
    assert!(dot3(vec3f(1, 2, 3), vec3f(4, 5, 6)) == 32.0);
}

#[test]
fn test_vec3f_cross() {
    assert!(cross(vec3f(1, 0, 0), vec3f(0, 1, 0)) == vec3f(0, 0, 1));
}

#[test]
fn test_vec3f_lerp() {
    let p0 = vec3f(1.0, 2.0, 3.0);
    let p1 = vec3f(-1.0, -2.0, -3.0);
    assert!(lerp3(&p0, &p1, 0.0) == p0);
    assert!(lerp3(&p0, &p1, 0.25) == vec3f(0.5, 1.0, 1.5));
    assert!(lerp3(&p0, &p1, 0.5) == vec3f(0.0, 0.0, 0.0));
    assert!(lerp3(&p0, &p1, 1.0) == p1);
}
<commit_msg>Add Vec3f::project_onto<commit_after>// Copyright 2015 Nicholas Bishop
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::ops::{Add, Div, Mul, Sub};

/// Vector with three f32 components
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Vec3f {
    pub x: f32,
    pub y: f32,
    pub z: f32
}

impl Vec3f {
    /// Create a Vec3f from three components
    pub fn new(x: f32, y: f32, z: f32) -> Vec3f {
        Vec3f { x: x,
                y: y,
                z: z }
    }

    /// Create a Vec3f with all components set to the same scalar
    pub fn from_scalar<T: CastF32>(s: T) -> Vec3f {
        let f = s.as_f32();
        Vec3f {
            x: f,
            y: f,
            z: f
        }
    }

    /// Squared length of the vector
    pub fn magnitude_squared(&self) -> f32 {
        dot3(*self, *self)
    }

    /// Length of the vector
    pub fn magnitude(&self) -> f32 {
        self.magnitude_squared().sqrt()
    }

    /// Create a normalized copy, or None if the magnitude is zero
    pub fn normalized(&self) -> Option<Vec3f> {
        let m = self.magnitude();
        if m == 0.0 {
            None
        }
        else {
            let f = 1.0 / m;
            Some((*self) * f)
        }
    }

    /// Projection of `self` into `v`, or None if the magnitude of
    /// `b` is zero.
    pub fn project_onto(&self, v: Vec3f) -> Option<Vec3f> {
        if v == ZERO_3F {
            None
        }
        else {
            Some(v * (dot3(*self, v) / dot3(v, v)))
        }
    }
}

/// Vec3f(0.0, 0.0, 0.0)
pub const ZERO_3F: Vec3f = Vec3f { x: 0.0, y: 0.0, z: 0.0 };

/// Convert a numeric type to an f32
pub trait CastF32 { fn as_f32(&self) -> f32; }

impl CastF32 for f32 { fn as_f32(&self) -> f32 { *self } }
impl CastF32 for f64 { fn as_f32(&self) -> f32 { *self as f32 } }

impl CastF32 for i8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for i64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for isize { fn as_f32(&self) -> f32 { *self as f32 } }

impl CastF32 for u8  { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u16 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u32 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for u64 { fn as_f32(&self) -> f32 { *self as f32 } }
impl CastF32 for usize { fn as_f32(&self) -> f32 { *self as f32 } }

/// Create a Vec3f from x, y, and z inputs
///
/// This is a convenience function that provides a little more
/// flexibility than Vec3f::new in that it will happily take numbers
/// that aren't f32 (including a mix of different types for each
/// component). Vec3f is such a common type that it seems reasonable
/// to provide a little extra ease of use.
pub fn vec3f<X: CastF32, Y: CastF32, Z: CastF32>(x: X, y: Y, z: Z) -> Vec3f {
    Vec3f { x: x.as_f32(), y: y.as_f32(), z: z.as_f32() }
}

/// Inner product of two Vec3f inputs
pub fn dot3(a: Vec3f, b: Vec3f) -> f32 {
    let v = a * b;
    v.x + v.y + v.z
}

/// Cross product of two Vec3f inputs
pub fn cross(a: Vec3f, b: Vec3f) -> Vec3f {
    Vec3f::new(a.y * b.z - a.z * b.y,
               a.z * b.x - a.x * b.z,
               a.x * b.y - a.y * b.x)
}

/// Distance between two points
pub fn distance3(a: Vec3f, b: Vec3f) -> f32 {
    (a - b).magnitude()
}

/// Linearly interpolate between two points by the factor `t`. When
/// `t` is zero the result is `p0`, and when `t` is one the result is
/// `p1`. The range of `t` is not clamped.
pub fn lerp3(p0: &Vec3f, p1: &Vec3f, t: f32) -> Vec3f {
    let n = 1.0 - t;
    Vec3f::new(p0.x * n + p1.x * t,
               p0.y * n + p1.y * t,
               p0.z * n + p1.z * t)
}

impl Add for Vec3f {
    type Output = Vec3f;
    fn add(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x + v.x, self.y + v.y, self.z + v.z)
    }
}

impl Add<f32> for Vec3f {
    type Output = Vec3f;
    fn add(self, s: f32) -> Vec3f {
        Vec3f::new(self.x + s, self.y + s, self.z + s)
    }
}

impl Div for Vec3f {
    type Output = Vec3f;
    fn div(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x / v.x, self.y / v.y, self.z / v.z)
    }
}

impl Mul<Vec3f> for Vec3f {
    type Output = Vec3f;
    fn mul(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x * v.x, self.y * v.y, self.z * v.z)
    }
}

impl Mul<f32> for Vec3f {
    type Output = Vec3f;
    fn mul(self, f: f32) -> Vec3f {
        Vec3f::new(self.x * f, self.y * f, self.z * f)
    }
}

impl Sub for Vec3f {
    type Output = Vec3f;
    fn sub(self, v: Vec3f) -> Vec3f {
        Vec3f::new(self.x - v.x, self.y - v.y, self.z - v.z)
    }
}

impl Sub<f32> for Vec3f {
    type Output = Vec3f;
    fn sub(self, s: f32) -> Vec3f {
        Vec3f::new(self.x - s, self.y - s, self.z - s)
    }
}

#[test]
fn test_vec3f_create() {
    vec3f(1.0f32, 2, 3i32);
    assert!(Vec3f::from_scalar(1) == vec3f(1, 1, 1));
}

#[test]
fn test_vec3f_magnitude() {
    let v = vec3f(-4, 0, 0);
    assert!(v.magnitude_squared() == 16.0);
    assert!(v.magnitude() == 4.0);
}

#[test]
fn test_vec3f_distance() {
    assert!(distance3(vec3f(0, -4, 0), vec3f(0, 4, 0)) == 8.0);
}

#[test]
fn test_vec3f_normalized() {
    assert_eq!(vec3f(0, 0, 0).normalized(), None);
    assert_eq!(vec3f(0.5, 0, 0).normalized(), Some(vec3f(1, 0, 0)));
}

#[test]
fn test_vec3f_project_onto() {
    let z = vec3f(0, 0, 0);
    let a = vec3f(1, 0, 0);
    let b = vec3f(1, 1, 0);
    assert_eq!(a.project_onto(z), None);
    assert_eq!(a.project_onto(b).unwrap(), vec3f(0.5, 0.5, 0));
}

#[test]
fn test_vec3f_arithmetic() {
    let a = vec3f(1, 2, 3);
    let b = vec3f(4, 5, 6);
    assert!(a + b == vec3f(5, 7, 9));
    assert!(a - b == vec3f(-3, -3, -3));
    assert!(a * b == vec3f(4, 10, 18));
    assert!(a / b == vec3f(0.25, 2.0 / 5.0, 0.5));
}

#[test]
fn test_vec3f_dot() {
    assert!(dot3(vec3f(1, 2, 3), vec3f(4, 5, 6)) == 32.0);
}

#[test]
fn test_vec3f_cross() {
    assert!(cross(vec3f(1, 0, 0), vec3f(0, 1, 0)) == vec3f(0, 0, 1));
}

#[test]
fn test_vec3f_lerp() {
    let p0 = vec3f(1.0, 2.0, 3.0);
    let p1 = vec3f(-1.0, -2.0, -3.0);
    assert!(lerp3(&p0, &p1, 0.0) == p0);
    assert!(lerp3(&p0, &p1, 0.25) == vec3f(0.5, 1.0, 1.5));
    assert!(lerp3(&p0, &p1, 0.5) == vec3f(0.0, 0.0, 0.0));
    assert!(lerp3(&p0, &p1, 1.0) == p1);
}
<|endoftext|>


<commit_before>
use button;
use drop_down_list;
use envelope_editor;
use number_dialer;
use slider;
use text_box;
use toggle;
use xy_pad;

/// Represents the placement of the widget including
/// x / y position, width and height.
#[derive(Clone, Copy)]
pub enum Placing {
    Place(f64, f64, f64, f64), // (x, y, w, h)
    NoPlace,
}

impl Placing {
    pub fn down(&self, padding: f64) -> (f64, f64) {
        match self {
            &Placing::Place(x, y, _, h) => (x, y + h + padding),
            &Placing::NoPlace => (0.0, 0.0),
        }
    }
    pub fn up(&self, padding: f64) -> (f64, f64) {
        match self {
            &Placing::Place(x, y, _, _) => (x, y - padding),
            &Placing::NoPlace => (0.0, 0.0),
        }
    }
    pub fn left(&self, padding: f64) -> (f64, f64) {
        match self {
            &Placing::Place(x, y, _, _) => (x - padding, y),
            &Placing::NoPlace => (0.0, 0.0),
        }
    }
    pub fn right(&self, padding: f64) -> (f64, f64) {
        match self {
            &Placing::Place(x, y, w, _) => (x + w + padding, y),
            &Placing::NoPlace => (0.0, 0.0),
        }
    }
}

/// Algebraic widget type for storing in ui_context
/// and for ease of state-matching.
#[derive(Copy, Clone)]
pub enum Widget {
    NoWidget,
    Button(button::State),
    DropDownList(drop_down_list::State),
    EnvelopeEditor(envelope_editor::State),
    NumberDialer(number_dialer::State),
    Slider(slider::State),
    TextBox(text_box::State),
    Toggle(toggle::State),
    XYPad(xy_pad::State),
}

impl Widget {
    pub fn matches(&self, other: &Widget) -> bool {
        match (self, other) {
            (&Widget::NoWidget, &Widget::NoWidget) => true,
            (&Widget::Button(_), &Widget::Button(_)) => true,
            (&Widget::DropDownList(_), &Widget::DropDownList(_)) => true,
            (&Widget::EnvelopeEditor(_), &Widget::EnvelopeEditor(_)) => true,
            (&Widget::NumberDialer(_), &Widget::NumberDialer(_)) => true,
            (&Widget::Slider(_), &Widget::Slider(_)) => true,
            (&Widget::TextBox(_), &Widget::TextBox(_)) => true,
            (&Widget::Toggle(_), &Widget::Toggle(_)) => true,
            (&Widget::XYPad(_), &Widget::XYPad(_)) => true,
            _ => false
        }
    }
}

/// Default widget state property.
#[derive(Copy, Clone)]
pub struct DefaultWidgetState(pub Widget);
<commit_msg>Removed `DefaultWidgetState`<commit_after>
use button;
use drop_down_list;
use envelope_editor;
use number_dialer;
use slider;
use text_box;
use toggle;
use xy_pad;

/// Represents the placement of the widget including
/// x / y position, width and height.
#[derive(Clone, Copy)]
pub enum Placing {
    Place(f64, f64, f64, f64), // (x, y, w, h)
    NoPlace,
}

impl Placing {
    pub fn down(&self, padding: f64) -> (f64, f64) {
        match self {
            &Placing::Place(x, y, _, h) => (x, y + h + padding),
            &Placing::NoPlace => (0.0, 0.0),
        }
    }
    pub fn up(&self, padding: f64) -> (f64, f64) {
        match self {
            &Placing::Place(x, y, _, _) => (x, y - padding),
            &Placing::NoPlace => (0.0, 0.0),
        }
    }
    pub fn left(&self, padding: f64) -> (f64, f64) {
        match self {
            &Placing::Place(x, y, _, _) => (x - padding, y),
            &Placing::NoPlace => (0.0, 0.0),
        }
    }
    pub fn right(&self, padding: f64) -> (f64, f64) {
        match self {
            &Placing::Place(x, y, w, _) => (x + w + padding, y),
            &Placing::NoPlace => (0.0, 0.0),
        }
    }
}

/// Algebraic widget type for storing in ui_context
/// and for ease of state-matching.
#[derive(Copy, Clone)]
pub enum Widget {
    NoWidget,
    Button(button::State),
    DropDownList(drop_down_list::State),
    EnvelopeEditor(envelope_editor::State),
    NumberDialer(number_dialer::State),
    Slider(slider::State),
    TextBox(text_box::State),
    Toggle(toggle::State),
    XYPad(xy_pad::State),
}

impl Widget {
    pub fn matches(&self, other: &Widget) -> bool {
        match (self, other) {
            (&Widget::NoWidget, &Widget::NoWidget) => true,
            (&Widget::Button(_), &Widget::Button(_)) => true,
            (&Widget::DropDownList(_), &Widget::DropDownList(_)) => true,
            (&Widget::EnvelopeEditor(_), &Widget::EnvelopeEditor(_)) => true,
            (&Widget::NumberDialer(_), &Widget::NumberDialer(_)) => true,
            (&Widget::Slider(_), &Widget::Slider(_)) => true,
            (&Widget::TextBox(_), &Widget::TextBox(_)) => true,
            (&Widget::Toggle(_), &Widget::Toggle(_)) => true,
            (&Widget::XYPad(_), &Widget::XYPad(_)) => true,
            _ => false
        }
    }
}
<|endoftext|>


<commit_before>use orbclient::{self, Renderer};
use orbclient::color::Color;
use std::cell::{Cell, RefCell};
use std::sync::Arc;

use super::{Event, Point, Rect, Widget};
use theme::WINDOW_BACKGROUND;

extern crate orbfont;

pub struct WindowRenderer<'a> {
    inner: &'a mut orbclient::Window,
    font: &'a Option<orbfont::Font>
}

impl<'a> WindowRenderer<'a> {
    pub fn new(inner: &'a mut orbclient::Window, font: &'a Option<orbfont::Font>) -> WindowRenderer<'a> {
        WindowRenderer { inner: inner, font: font }
    }
}

impl<'a> Renderer for WindowRenderer<'a> {
    fn width(&self) -> u32 {
        self.inner.width()
    }

    fn height(&self) -> u32 {
        self.inner.height()
    }

    fn data(&self) -> &[Color] {
        self.inner.data()
    }

    fn data_mut(&mut self) -> &mut [Color] {
        self.inner.data_mut()
    }

    fn sync(&mut self) -> bool {
        self.inner.sync()
    }

    fn char(&mut self, x: i32, y: i32, c: char, color: Color) {
        if let Some(ref font) = *self.font {
            font.render(&c.to_string(), 16.0).draw(self.inner, x, y, color)
        }else{
            self.inner.char(x, y, c, color);
        }
    }
}

impl<'a> Drop for WindowRenderer<'a> {
    fn drop(&mut self) {
        self.inner.sync();
    }
}

pub struct Window {
    inner: RefCell<orbclient::Window>,
    font: Option<orbfont::Font>,
    pub widgets: RefCell<Vec<Arc<Widget>>>,
    pub widget_focus: Cell<usize>,
    pub bg: Color,
    pub running: Cell<bool>
}

impl Window {
    pub fn new(rect: Rect, title: &str) -> Self {
        Window {
            inner: RefCell::new(orbclient::Window::new(rect.x, rect.y, rect.width, rect.height, title).unwrap()),
            font: orbfont::Font::find(None, None, None).ok(),
            widgets: RefCell::new(Vec::new()),
            widget_focus: Cell::new(0),
            bg: WINDOW_BACKGROUND,
            running: Cell::new(true),
        }
    }

    pub fn close(&self) {
        self.running.set(false);
    }

    pub fn add<T: Widget>(&self, widget: &Arc<T>) -> usize {
        let mut widgets = self.widgets.borrow_mut();
        let id = widgets.len();
        widgets.push(widget.clone());
        id
    }

    pub fn draw(&self) {
        let mut inner = self.inner.borrow_mut();
        inner.set(self.bg);

        let mut renderer = WindowRenderer::new(&mut *inner, &self.font);
        for i in 0..self.widgets.borrow().len() {
            if let Some(widget) = self.widgets.borrow().get(i) {
                widget.draw(&mut renderer, self.widget_focus.get() == i);
            }
        }
    }

    pub fn exec(&self) {
        let mut events = Vec::new();
        events.push(Event::Init);

        let mut redraw = true;

        'event: while self.running.get() {
            for event in events.drain(..) {
                for i in 0..self.widgets.borrow().len() {
                    if let Some(widget) = self.widgets.borrow().get(i) {
                        if widget.event(event, self.widget_focus.get() == i, &mut redraw) {
                            if self.widget_focus.get() != i {
                                self.widget_focus.set(i);
                                redraw = true;
                            }
                        }
                    }
                }
            }

            if redraw {
                self.draw();
                redraw = false;
            }

            for orbital_event in self.inner.borrow_mut().events() {
                match orbital_event.to_option() {
                    orbclient::EventOption::Mouse(mouse_event) => {
                        events.push(Event::Mouse {
                            point: Point::new(mouse_event.x, mouse_event.y),
                            left_button: mouse_event.left_button,
                            middle_button: mouse_event.middle_button,
                            right_button: mouse_event.right_button,
                        })
                    }
                    orbclient::EventOption::Key(key_event) => {
                        if key_event.pressed {
                            match key_event.scancode {
                                orbclient::K_BKSP => events.push(Event::Backspace),
                                orbclient::K_DEL => events.push(Event::Delete),
                                orbclient::K_HOME => events.push(Event::Home),
                                orbclient::K_END => events.push(Event::End),
                                orbclient::K_UP => events.push(Event::UpArrow),
                                orbclient::K_DOWN => events.push(Event::DownArrow),
                                orbclient::K_LEFT => events.push(Event::LeftArrow),
                                orbclient::K_RIGHT => events.push(Event::RightArrow),
                                _ => {
                                    match key_event.character {
                                        '\0' => (),
                                        '\x1B' => (),
                                        '\n' => events.push(Event::Enter),
                                        _ => events.push(Event::Text { c: key_event.character }),
                                    }
                                }
                            }
                        }
                    }
                    orbclient::EventOption::Quit(_quit_event) => break 'event,
                    _ => (),
                };
            }
        }
    }
}
<commit_msg>Improve performance of character render<commit_after>use orbclient::{self, Renderer};
use orbclient::color::Color;
use std::cell::{Cell, RefCell};
use std::sync::Arc;

use super::{Event, Point, Rect, Widget};
use theme::WINDOW_BACKGROUND;

extern crate orbfont;

pub struct WindowRenderer<'a> {
    inner: &'a mut orbclient::Window,
    font: &'a Option<orbfont::Font>
}

impl<'a> WindowRenderer<'a> {
    pub fn new(inner: &'a mut orbclient::Window, font: &'a Option<orbfont::Font>) -> WindowRenderer<'a> {
        WindowRenderer { inner: inner, font: font }
    }
}

impl<'a> Renderer for WindowRenderer<'a> {
    fn width(&self) -> u32 {
        self.inner.width()
    }

    fn height(&self) -> u32 {
        self.inner.height()
    }

    fn data(&self) -> &[Color] {
        self.inner.data()
    }

    fn data_mut(&mut self) -> &mut [Color] {
        self.inner.data_mut()
    }

    fn sync(&mut self) -> bool {
        self.inner.sync()
    }

    fn char(&mut self, x: i32, y: i32, c: char, color: Color) {
        if let Some(ref font) = *self.font {
            let mut buf = [0; 4];
            font.render(&c.encode_utf8(&mut buf), 16.0).draw(self.inner, x, y, color)
        }else{
            self.inner.char(x, y, c, color);
        }
    }
}

impl<'a> Drop for WindowRenderer<'a> {
    fn drop(&mut self) {
        self.inner.sync();
    }
}

pub struct Window {
    inner: RefCell<orbclient::Window>,
    font: Option<orbfont::Font>,
    pub widgets: RefCell<Vec<Arc<Widget>>>,
    pub widget_focus: Cell<usize>,
    pub bg: Color,
    pub running: Cell<bool>
}

impl Window {
    pub fn new(rect: Rect, title: &str) -> Self {
        Window {
            inner: RefCell::new(orbclient::Window::new(rect.x, rect.y, rect.width, rect.height, title).unwrap()),
            font: orbfont::Font::find(None, None, None).ok(),
            widgets: RefCell::new(Vec::new()),
            widget_focus: Cell::new(0),
            bg: WINDOW_BACKGROUND,
            running: Cell::new(true),
        }
    }

    pub fn close(&self) {
        self.running.set(false);
    }

    pub fn add<T: Widget>(&self, widget: &Arc<T>) -> usize {
        let mut widgets = self.widgets.borrow_mut();
        let id = widgets.len();
        widgets.push(widget.clone());
        id
    }

    pub fn draw(&self) {
        let mut inner = self.inner.borrow_mut();
        inner.set(self.bg);

        let mut renderer = WindowRenderer::new(&mut *inner, &self.font);
        for i in 0..self.widgets.borrow().len() {
            if let Some(widget) = self.widgets.borrow().get(i) {
                widget.draw(&mut renderer, self.widget_focus.get() == i);
            }
        }
    }

    pub fn exec(&self) {
        let mut events = Vec::new();
        events.push(Event::Init);

        let mut redraw = true;

        'event: while self.running.get() {
            for event in events.drain(..) {
                for i in 0..self.widgets.borrow().len() {
                    if let Some(widget) = self.widgets.borrow().get(i) {
                        if widget.event(event, self.widget_focus.get() == i, &mut redraw) {
                            if self.widget_focus.get() != i {
                                self.widget_focus.set(i);
                                redraw = true;
                            }
                        }
                    }
                }
            }

            if redraw {
                self.draw();
                redraw = false;
            }

            for orbital_event in self.inner.borrow_mut().events() {
                match orbital_event.to_option() {
                    orbclient::EventOption::Mouse(mouse_event) => {
                        events.push(Event::Mouse {
                            point: Point::new(mouse_event.x, mouse_event.y),
                            left_button: mouse_event.left_button,
                            middle_button: mouse_event.middle_button,
                            right_button: mouse_event.right_button,
                        })
                    }
                    orbclient::EventOption::Key(key_event) => {
                        if key_event.pressed {
                            match key_event.scancode {
                                orbclient::K_BKSP => events.push(Event::Backspace),
                                orbclient::K_DEL => events.push(Event::Delete),
                                orbclient::K_HOME => events.push(Event::Home),
                                orbclient::K_END => events.push(Event::End),
                                orbclient::K_UP => events.push(Event::UpArrow),
                                orbclient::K_DOWN => events.push(Event::DownArrow),
                                orbclient::K_LEFT => events.push(Event::LeftArrow),
                                orbclient::K_RIGHT => events.push(Event::RightArrow),
                                _ => {
                                    match key_event.character {
                                        '\0' => (),
                                        '\x1B' => (),
                                        '\n' => events.push(Event::Enter),
                                        _ => events.push(Event::Text { c: key_event.character }),
                                    }
                                }
                            }
                        }
                    }
                    orbclient::EventOption::Quit(_quit_event) => break 'event,
                    _ => (),
                };
            }
        }
    }
}
<|endoftext|>